Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / shells / textfld.cxx
blobc75cb2c2f8d942f13bbbbb09de0803b8dd651331
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/beans/PropertyValues.hpp>
21 #include <AnnotationWin.hxx>
22 #include <comphelper/lok.hxx>
23 #include <hintids.hxx>
24 #include <IDocumentFieldsAccess.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/lnkbase.hxx>
27 #include <txtfld.hxx>
28 #include <svl/itempool.hxx>
29 #include <svl/numformat.hxx>
30 #include <tools/lineend.hxx>
31 #include <svl/whiter.hxx>
32 #include <svl/eitem.hxx>
33 #include <svl/macitem.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <sfx2/request.hxx>
36 #include <svx/postattr.hxx>
37 #include <svx/hlnkitem.hxx>
38 #include <svx/svxdlg.hxx>
39 #include <osl/diagnose.h>
40 #include <fmthdft.hxx>
41 #include <fmtinfmt.hxx>
42 #include <fldwrap.hxx>
43 #include <redline.hxx>
44 #include <view.hxx>
45 #include <viewopt.hxx>
46 #include <wrtsh.hxx>
47 #include <textsh.hxx>
48 #include <docufld.hxx>
49 #include <ddefld.hxx>
50 #include <fldmgr.hxx>
51 #include <uitool.hxx>
52 #include <cmdid.h>
53 #include <strings.hrc>
54 #include <sfx2/event.hxx>
55 #include <swabstdlg.hxx>
56 #include <doc.hxx>
57 #include <PostItMgr.hxx>
58 #include <swmodule.hxx>
60 #include <editeng/ulspitem.hxx>
61 #include <xmloff/odffields.hxx>
62 #include <IDocumentContentOperations.hxx>
63 #include <IDocumentRedlineAccess.hxx>
64 #include <IDocumentUndoRedo.hxx>
65 #include <svl/zforlist.hxx>
66 #include <svl/zformat.hxx>
67 #include <svx/xfillit0.hxx>
68 #include <svx/pageitem.hxx>
69 #include <comphelper/sequenceashashmap.hxx>
70 #include <IMark.hxx>
71 #include <officecfg/Office/Compatibility.hxx>
72 #include <ndtxt.hxx>
73 #include <translatehelper.hxx>
74 #include <sfx2/dispatch.hxx>
77 using namespace nsSwDocInfoSubType;
79 static OUString lcl_BuildTitleWithRedline( const SwRangeRedline *pRedline )
81 const OUString sTitle(SwResId(STR_REDLINE_COMMENT));
83 TranslateId pResId;
84 switch( pRedline->GetType() )
86 case RedlineType::Insert:
87 pResId = STR_REDLINE_INSERTED;
88 break;
89 case RedlineType::Delete:
90 pResId = STR_REDLINE_DELETED;
91 break;
92 case RedlineType::Format:
93 case RedlineType::ParagraphFormat:
94 pResId = STR_REDLINE_FORMATTED;
95 break;
96 case RedlineType::Table:
97 pResId = STR_REDLINE_TABLECHG;
98 break;
99 case RedlineType::FmtColl:
100 pResId = STR_REDLINE_FMTCOLLSET;
101 break;
102 default:
103 return sTitle;
106 return sTitle + SwResId(pResId);
109 void SwTextShell::ExecField(SfxRequest &rReq)
111 SwWrtShell& rSh = GetShell();
112 const SfxPoolItem* pItem = nullptr;
114 sal_uInt16 nSlot = rReq.GetSlot();
115 const SfxItemSet* pArgs = rReq.GetArgs();
116 if(pArgs)
117 pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
119 bool bMore = false;
120 bool bIsText = true;
121 SwFieldTypesEnum nInsertType = SwFieldTypesEnum::Date;
122 sal_uInt16 nInsertSubType = 0;
123 sal_uInt32 nInsertFormat = 0;
125 switch(nSlot)
127 case FN_EDIT_FIELD:
129 SwField* pField = rSh.GetCurField(true);
130 if( pField )
132 switch ( pField->GetTypeId() )
134 case SwFieldTypesEnum::DDE:
136 ::sfx2::SvBaseLink& rLink = static_cast<SwDDEFieldType*>(pField->GetTyp())->
137 GetBaseLink();
138 if(rLink.IsVisible())
140 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
141 ScopedVclPtr<SfxAbstractLinksDialog> pDlg(pFact->CreateLinksDialog(GetView().GetFrameWeld(), &rSh.GetLinkManager(), false, &rLink));
142 pDlg->Execute();
144 break;
146 default:
148 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
149 ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwFieldEditDlg( GetView() ));
150 pDlg->Execute();
154 break;
156 case FN_UPDATE_SEL_FIELD:
158 SwField *pField = rSh.GetCurField();
160 if (pField)
162 rSh.UpdateOneField(*pField);
164 break;
166 case FN_EXECUTE_MACROFIELD:
168 SwField* pField = rSh.GetCurField();
169 if(pField && pField->GetTyp()->Which() == SwFieldIds::Macro)
172 const OUString& rMacro = static_cast<SwMacroField*>(pField)->GetMacro();
173 sal_Int32 nPos = rMacro.indexOf('.');
174 if(nPos != -1)
176 SvxMacro aMacro( rMacro.copy(nPos + 1), rMacro.copy(0,nPos), STARBASIC );
177 rSh.ExecMacro(aMacro);
181 break;
183 case FN_GOTO_NEXT_INPUTFLD:
184 case FN_GOTO_PREV_INPUTFLD:
186 bool bRet = false;
187 SwFieldType* pField = rSh.GetFieldType( 0, SwFieldIds::Input );
188 const bool bAddSetExpressionFields = !( rSh.GetViewOptions()->IsReadonly() );
189 if ( pField != nullptr
190 && rSh.MoveFieldType(
191 pField,
192 FN_GOTO_NEXT_INPUTFLD == nSlot,
193 SwFieldIds::Unknown,
194 bAddSetExpressionFields ) )
196 rSh.ClearMark();
197 if (!rSh.IsMultiSelection()
198 && (nullptr != dynamic_cast<const SwTextInputField*>(
199 SwCursorShell::GetTextFieldAtCursor(rSh.GetCursor(), ::sw::GetTextAttrMode::Default))))
201 rSh.SttSelect();
202 rSh.SelectTextModel(
203 SwCursorShell::StartOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) + 1,
204 SwCursorShell::EndOfInputFieldAtPos( *(rSh.GetCursor()->Start()) ) - 1 );
206 else if (SwField* pCurrentField = rSh.GetCurField(true))
208 rSh.StartInputFieldDlg(pCurrentField, false, false, GetView().GetFrameWeld());
210 bRet = true;
213 rReq.SetReturnValue( SfxBoolItem( nSlot, bRet ));
215 break;
217 case FN_GOTO_MARK:
219 const SfxStringItem* pName = rReq.GetArg<SfxStringItem>(FN_GOTO_MARK);
220 if (pName)
222 rSh.GotoMark(pName->GetValue());
225 break;
226 default:
227 bMore = true;
229 if(!bMore)
230 return;
232 // Here come the slots with FieldMgr.
233 SwFieldMgr aFieldMgr(GetShellPtr());
234 switch(nSlot)
236 case FN_INSERT_DBFIELD:
238 bool bRes = false;
239 if( pItem )
241 sal_uInt32 nFormat = 0;
242 SwFieldTypesEnum nType = SwFieldTypesEnum::Date;
243 OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue();
244 OUString aPar2;
245 sal_Int32 nCommand = 0;
247 if( const SfxUInt16Item* pFieldItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE,
248 false ))
249 nType = static_cast<SwFieldTypesEnum>(pFieldItem->GetValue());
250 aPar1 += OUStringChar(DB_DELIM);
251 if( SfxItemState::SET == pArgs->GetItemState(
252 FN_PARAM_1, false, &pItem ))
254 aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue();
256 if( SfxItemState::SET == pArgs->GetItemState(
257 FN_PARAM_3, false, &pItem ))
258 nCommand = static_cast<const SfxInt32Item*>(pItem)->GetValue();
259 aPar1 += OUStringChar(DB_DELIM)
260 + OUString::number(nCommand)
261 + OUStringChar(DB_DELIM);
262 if( SfxItemState::SET == pArgs->GetItemState(
263 FN_PARAM_2, false, &pItem ))
265 aPar1 += static_cast<const SfxStringItem *>(pItem)->GetValue();
267 if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet(
268 FN_PARAM_FIELD_CONTENT, false ))
269 aPar2 = pContentItem->GetValue();
270 if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet(
271 FN_PARAM_FIELD_FORMAT, false ))
272 nFormat = pFormatItem->GetValue();
273 OSL_FAIL("Command is not yet used");
274 SwInsertField_Data aData(nType, 0, aPar1, aPar2, nFormat, GetShellPtr(), ' '/*separator*/ );
275 bRes = aFieldMgr.InsertField(aData);
277 rReq.SetReturnValue(SfxBoolItem( nSlot, bRes ));
279 break;
280 case FN_INSERT_FIELD_CTRL:
281 case FN_INSERT_FIELD:
283 bool bRes = false;
284 if( pItem && nSlot != FN_INSERT_FIELD_CTRL)
286 sal_uInt32 nFormat = 0;
287 SwFieldTypesEnum nType = SwFieldTypesEnum::Date;
288 sal_uInt16 nSubType = 0;
289 OUString aPar1 = static_cast<const SfxStringItem *>(pItem)->GetValue();
290 OUString aPar2;
291 sal_Unicode cSeparator = ' ';
293 if( const SfxUInt16Item* pTypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_TYPE,
294 false ))
295 nType = static_cast<SwFieldTypesEnum>(pTypeItem->GetValue());
296 else if (pArgs->GetItemState(FN_PARAM_4, false, &pItem) == SfxItemState::SET)
298 const OUString& rTypeName = static_cast<const SfxStringItem *>(pItem)->GetValue();
299 nType = SwFieldTypeFromString(rTypeName);
301 if( const SfxUInt16Item* pSubtypeItem = pArgs->GetItemIfSet( FN_PARAM_FIELD_SUBTYPE,
302 false ))
303 nSubType = pSubtypeItem->GetValue();
304 if( const SfxStringItem* pContentItem = pArgs->GetItemIfSet(
305 FN_PARAM_FIELD_CONTENT, false ))
306 aPar2 = pContentItem->GetValue();
307 if( const SfxUInt32Item* pFormatItem = pArgs->GetItemIfSet(
308 FN_PARAM_FIELD_FORMAT, false ))
309 nFormat = pFormatItem->GetValue();
310 if( SfxItemState::SET == pArgs->GetItemState(
311 FN_PARAM_3, false, &pItem ))
313 OUString sTmp = static_cast<const SfxStringItem *>(pItem)->GetValue();
314 if(!sTmp.isEmpty())
315 cSeparator = sTmp[0];
317 if (pArgs->GetItemState(FN_PARAM_5, false, &pItem) == SfxItemState::SET)
319 // Wrap the field in the requested container instead of inserting it
320 // directly at the cursor position.
321 const OUString& rWrapper = static_cast<const SfxStringItem *>(pItem)->GetValue();
322 if (rWrapper == "Footnote")
324 GetShellPtr()->InsertFootnote(OUString());
326 else if (rWrapper == "Endnote")
328 GetShellPtr()->InsertFootnote(OUString(), /*bEndNote=*/true);
331 SwInsertField_Data aData(nType, nSubType, aPar1, aPar2, nFormat, GetShellPtr(), cSeparator );
332 bRes = aFieldMgr.InsertField( aData );
334 else
336 //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active
337 if(!GetView().GetViewFrame().IsInModalMode())
339 SfxViewFrame& rVFrame = GetView().GetViewFrame();
340 rVFrame.ToggleChildWindow(FN_INSERT_FIELD);
341 bRes = rVFrame.GetChildWindow( nSlot ) != nullptr;
342 Invalidate(rReq.GetSlot());
343 Invalidate(FN_INSERT_FIELD_CTRL);
344 rReq.Ignore();
347 rReq.SetReturnValue(SfxBoolItem( nSlot, bRes ));
349 break;
351 case FN_INSERT_REF_FIELD:
353 SfxViewFrame& rVFrame = GetView().GetViewFrame();
354 if (!rVFrame.HasChildWindow(FN_INSERT_FIELD))
355 rVFrame.ToggleChildWindow(FN_INSERT_FIELD); // Show dialog
357 // Switch Fielddlg at a new TabPage
358 sal_uInt16 nId = SwFieldDlgWrapper::GetChildWindowId();
359 SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame.GetChildWindow(nId));
360 if (pWrp)
361 pWrp->ShowReferencePage();
362 rReq.Ignore();
364 break;
365 case FN_DELETE_COMMENT:
367 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
368 if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
370 GetView().GetPostItMgr()->Delete(pIdItem->GetValue().toUInt32());
372 else if ( GetView().GetPostItMgr() &&
373 GetView().GetPostItMgr()->HasActiveSidebarWin() )
375 GetView().GetPostItMgr()->DeleteActiveSidebarWin();
377 break;
379 case FN_DELETE_COMMENT_THREAD:
381 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
382 if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
384 GetView().GetPostItMgr()->DeleteCommentThread(pIdItem->GetValue().toUInt32());
386 else if ( GetView().GetPostItMgr() &&
387 GetView().GetPostItMgr()->HasActiveSidebarWin() )
389 GetView().GetPostItMgr()->DeleteActiveSidebarWin();
391 break;
393 case FN_RESOLVE_NOTE:
395 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
396 if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
398 GetView().GetPostItMgr()->ToggleResolved(pIdItem->GetValue().toUInt32());
400 break;
402 case FN_RESOLVE_NOTE_THREAD:
404 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
405 if (pIdItem && !pIdItem->GetValue().isEmpty() && GetView().GetPostItMgr())
407 GetView().GetPostItMgr()->ToggleResolvedForThread(pIdItem->GetValue().toUInt32());
409 break;
411 case FN_DELETE_ALL_NOTES:
412 if ( GetView().GetPostItMgr() )
413 GetView().GetPostItMgr()->Delete();
414 break;
415 case FN_FORMAT_ALL_NOTES:
417 SwPostItMgr* pPostItMgr = GetView().GetPostItMgr();
418 if (pPostItMgr)
419 pPostItMgr->ExecuteFormatAllDialog(GetView());
421 break;
422 case FN_DELETE_NOTE_AUTHOR:
424 const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot);
425 if ( pNoteItem && GetView().GetPostItMgr() )
426 GetView().GetPostItMgr()->Delete( pNoteItem->GetValue() );
428 break;
429 case FN_HIDE_NOTE:
430 if ( GetView().GetPostItMgr() &&
431 GetView().GetPostItMgr()->HasActiveSidebarWin() )
433 GetView().GetPostItMgr()->HideActiveSidebarWin();
435 break;
436 case FN_HIDE_ALL_NOTES:
437 if ( GetView().GetPostItMgr() )
438 GetView().GetPostItMgr()->Hide();
439 break;
440 case FN_HIDE_NOTE_AUTHOR:
442 const SfxStringItem* pNoteItem = rReq.GetArg<SfxStringItem>(nSlot);
443 if ( pNoteItem && GetView().GetPostItMgr() )
444 GetView().GetPostItMgr()->Hide( pNoteItem->GetValue() );
446 break;
447 case FN_REPLY:
449 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
450 if (pIdItem && !pIdItem->GetValue().isEmpty())
452 SwFieldType* pType = rSh.GetDoc()->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Postit, OUString(), false);
453 if(pType->FindFormatForPostItId(pIdItem->GetValue().toUInt32()))
455 auto pMgr = GetView().GetPostItMgr();
456 auto pWin = pMgr->GetAnnotationWin(pIdItem->GetValue().toUInt32());
457 if(pWin)
459 OUString sText;
460 if(const auto pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT))
461 sText = pTextItem->GetValue();
462 pMgr->RegisterAnswerText(sText);
463 pWin->ExecuteCommand(nSlot);
468 break;
469 case FN_POSTIT:
471 rSh.InsertPostIt(aFieldMgr, rReq);
473 break;
474 case SID_EDIT_POSTIT:
476 const SvxPostItIdItem* pIdItem = rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
477 if (pIdItem && !pIdItem->GetValue().isEmpty())
479 const SvxPostItTextItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
480 OUString sText;
481 if ( pTextItem )
482 sText = pTextItem->GetValue();
484 sw::annotation::SwAnnotationWin* pAnnotationWin = GetView().GetPostItMgr()->GetAnnotationWin(pIdItem->GetValue().toUInt32());
485 if (pAnnotationWin)
487 pAnnotationWin->UpdateText(sText);
489 // explicit state update to get the Undo state right
490 GetView().AttrChangedNotify(nullptr);
494 break;
495 case FN_REDLINE_COMMENT:
497 /* this code can be used once we want redline comments in the margin, all other stuff can
498 then be deleted
499 String sComment;
500 const SwRangeRedline *pRedline = rSh.GetCurrRedline();
502 if (pRedline)
504 sComment = pRedline->GetComment();
505 if ( !sComment.Len() )
506 GetView().GetDocShell()->Broadcast(SwRedlineHint(pRedline,SWREDLINE_INSERTED));
507 const_cast<SwRangeRedline*>(pRedline)->Broadcast(SwRedlineHint(pRedline,SWREDLINE_FOCUS,&GetView()));
511 const SwRangeRedline *pRedline = rSh.GetCurrRedline();
512 SwDoc *pDoc = rSh.GetDoc();
513 // If index is specified, goto and select the appropriate redline
514 if (pArgs && pArgs->GetItemState(nSlot, false, &pItem) == SfxItemState::SET)
516 const sal_uInt32 nChangeId = static_cast<const SfxUInt32Item*>(pItem)->GetValue();
517 const SwRedlineTable& rRedlineTable = pDoc->getIDocumentRedlineAccess().GetRedlineTable();
518 for (SwRedlineTable::size_type nRedline = 0; nRedline < rRedlineTable.size(); ++nRedline)
520 if (nChangeId == rRedlineTable[nRedline]->GetId())
521 pRedline = rSh.GotoRedline(nRedline, true);
525 OUString sCommentText;
526 const SfxStringItem* pTextItem = rReq.GetArg<SvxPostItTextItem>(SID_ATTR_POSTIT_TEXT);
527 if (pTextItem)
528 sCommentText = pTextItem->GetValue();
530 if (pRedline)
532 // In case of LOK and comment text is already provided, skip
533 // dialog creation and just change the redline comment directly
534 if (comphelper::LibreOfficeKit::isActive() && !sCommentText.isEmpty())
536 rSh.SetRedlineComment(sCommentText);
537 GetView().AttrChangedNotify(nullptr);
538 MaybeNotifyRedlineModification(const_cast<SwRangeRedline&>(*pRedline), pRedline->GetDoc());
539 break;
542 OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
544 bool bTravel = false;
546 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
547 ::DialogGetRanges fnGetRange = pFact->GetDialogGetRangesFunc();
548 SfxItemSet aSet(GetPool(), fnGetRange());
549 aSet.Put(SvxPostItTextItem(sComment, SID_ATTR_POSTIT_TEXT));
550 aSet.Put(SvxPostItAuthorItem(pRedline->GetAuthorString(), SID_ATTR_POSTIT_AUTHOR));
552 aSet.Put( SvxPostItDateItem( GetAppLangDateTimeString(
553 pRedline->GetRedlineData().GetTimeStamp() ),
554 SID_ATTR_POSTIT_DATE ));
556 // Traveling only if more than one field.
557 rSh.StartAction();
559 rSh.Push();
560 const SwRangeRedline *pActRed = rSh.SelPrevRedline();
562 if (pActRed == pRedline)
563 { // New cursor is at the beginning of the current redlines.
564 rSh.Pop(); // Throw old cursor away
565 rSh.Push();
566 pActRed = rSh.SelPrevRedline();
569 bool bPrev = pActRed != nullptr;
570 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent);
571 rSh.EndAction();
573 rSh.ClearMark();
574 // Select current redline.
575 pActRed = rSh.SelNextRedline();
576 if (pActRed != pRedline)
577 rSh.SelPrevRedline();
579 rSh.StartAction();
580 rSh.Push();
581 pActRed = rSh.SelNextRedline();
582 bool bNext = pActRed != nullptr;
583 rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); // Restore cursor position
585 if( rSh.IsCursorPtAtEnd() )
586 rSh.SwapPam();
588 rSh.EndAction();
590 bTravel |= bNext || bPrev;
592 SvxAbstractDialogFactory* pFact2 = SvxAbstractDialogFactory::Create();
593 ScopedVclPtr<AbstractSvxPostItDialog> pDlg(pFact2->CreateSvxPostItDialog(GetView().GetFrameWeld(), aSet, bTravel));
594 pDlg->HideAuthor();
596 pDlg->SetText(lcl_BuildTitleWithRedline(pRedline));
598 if (bTravel)
600 pDlg->EnableTravel(bNext, bPrev);
601 pDlg->SetPrevHdl(LINK(this, SwTextShell, RedlinePrevHdl));
602 pDlg->SetNextHdl(LINK(this, SwTextShell, RedlineNextHdl));
605 SwViewShell::SetCareDialog(pDlg->GetDialog());
606 g_bNoInterrupt = true;
608 if ( pDlg->Execute() == RET_OK )
610 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
611 OUString sMsg(pOutSet->Get(SID_ATTR_POSTIT_TEXT).GetValue());
613 // Insert or change a comment
614 rSh.SetRedlineComment(sMsg);
617 SwViewShell::SetCareDialog(nullptr);
618 pDlg.disposeAndClear();
619 g_bNoInterrupt = false;
620 rSh.ClearMark();
621 GetView().AttrChangedNotify(nullptr);
624 break;
626 case FN_JAVAEDIT:
628 OUString aType, aText;
629 bool bIsUrl=false;
630 bool bNew=false;
631 bool bUpdate = false;
632 SwFieldMgr aMgr;
633 if ( pItem )
635 aText = static_cast<const SfxStringItem*>(pItem)->GetValue();
636 const SfxStringItem* pType = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
637 const SfxBoolItem* pIsUrl = rReq.GetArg<SfxBoolItem>(FN_PARAM_1);
638 if ( pType )
639 aType = pType->GetValue();
640 if ( pIsUrl )
641 bIsUrl = pIsUrl->GetValue();
643 SwScriptField* pField = static_cast<SwScriptField*>(aMgr.GetCurField());
644 bNew = !pField || (pField->GetTyp()->Which() != SwFieldIds::Script);
645 bUpdate = pField && ( bIsUrl != static_cast<bool>(pField->GetFormat()) || pField->GetPar2() != aType || pField->GetPar1() != aText );
647 else
649 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
650 ScopedVclPtr<AbstractJavaEditDialog> pDlg(pFact->CreateJavaEditDialog(GetView().GetFrameWeld(), &rSh));
651 if ( pDlg->Execute() )
653 aType = pDlg->GetScriptType();
654 aText = pDlg->GetScriptText();
655 bIsUrl = pDlg->IsUrl();
656 bNew = pDlg->IsNew();
657 bUpdate = pDlg->IsUpdate();
658 rReq.AppendItem( SfxStringItem( FN_JAVAEDIT, aText ) );
659 rReq.AppendItem( SfxStringItem( FN_PARAM_2, aType ) );
660 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bIsUrl ) );
664 if( bNew )
666 SwInsertField_Data aData(SwFieldTypesEnum::Script, 0, aType, aText, bIsUrl ? 1 : 0);
667 aMgr.InsertField(aData);
668 rReq.Done();
670 else if( bUpdate )
672 aMgr.UpdateCurField( bIsUrl ? 1 : 0, aType, aText );
673 rSh.SetUndoNoResetModified();
674 rReq.Done();
676 else
677 rReq.Ignore();
679 break;
681 case FN_INSERT_FLD_DATE :
683 nInsertType = SwFieldTypesEnum::Date;
684 bIsText = false;
685 // use long date format for Hungarian
686 SwPaM* pCursorPos = rSh.GetCursor();
687 if( pCursorPos )
689 LanguageType nLang = pCursorPos->GetPoint()->GetNode().GetTextNode()->GetLang(pCursorPos->GetPoint()->GetContentIndex());
690 if (nLang == LANGUAGE_HUNGARIAN)
691 nInsertFormat = rSh.GetNumberFormatter()->GetFormatIndex(NF_DATE_SYSTEM_LONG, nLang);
693 goto FIELD_INSERT;
695 case FN_INSERT_FLD_TIME :
696 nInsertType = SwFieldTypesEnum::Time;
697 bIsText = false;
698 goto FIELD_INSERT;
699 case FN_INSERT_FLD_PGNUMBER:
700 nInsertType = SwFieldTypesEnum::PageNumber;
701 nInsertFormat = SVX_NUM_PAGEDESC; // Like page template
702 bIsText = false;
703 goto FIELD_INSERT;
704 case FN_INSERT_FLD_PGCOUNT :
705 nInsertType = SwFieldTypesEnum::DocumentStatistics;
706 nInsertSubType = 0;
707 bIsText = false;
708 nInsertFormat = SVX_NUM_PAGEDESC;
709 goto FIELD_INSERT;
710 case FN_INSERT_FLD_TOPIC :
711 nInsertType = SwFieldTypesEnum::DocumentInfo;
712 nInsertSubType = DI_SUBJECT;
713 goto FIELD_INSERT;
714 case FN_INSERT_FLD_TITLE :
715 nInsertType = SwFieldTypesEnum::DocumentInfo;
716 nInsertSubType = DI_TITLE;
717 goto FIELD_INSERT;
718 case FN_INSERT_FLD_AUTHOR :
719 nInsertType = SwFieldTypesEnum::DocumentInfo;
720 nInsertSubType = DI_CREATE|DI_SUB_AUTHOR;
722 FIELD_INSERT:
724 //format conversion should only be done for number formatter formats
725 if(!nInsertFormat)
726 nInsertFormat = aFieldMgr.GetDefaultFormat(nInsertType, bIsText, rSh.GetNumberFormatter());
727 SwInsertField_Data aData(nInsertType, nInsertSubType,
728 OUString(), OUString(), nInsertFormat);
729 aFieldMgr.InsertField(aData);
730 rReq.Done();
732 break;
734 case FN_INSERT_TEXT_FORMFIELD:
736 OUString aFieldType(ODF_FORMTEXT);
737 const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
738 if (pFieldType)
740 // Allow overwriting the default type.
741 aFieldType = pFieldType->GetValue();
744 OUString aFieldCode;
745 const SfxStringItem* pFieldCode = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
746 if (pFieldCode)
748 // Allow specifying a field code/command.
749 aFieldCode = pFieldCode->GetValue();
752 if (rSh.HasReadonlySel())
754 // Inform the user that the request has been ignored.
755 auto xInfo = std::make_shared<weld::GenericDialogController>(
756 GetView().GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui",
757 "InfoReadonlyDialog");
758 weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {});
759 break;
762 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
764 SwPaM* pCursorPos = rSh.GetCursor();
765 if(pCursorPos)
767 // Insert five En Space into the text field so the field has extent
768 static constexpr OUStringLiteral vEnSpaces = u"\u2002\u2002\u2002\u2002\u2002";
769 OUString aFieldResult(vEnSpaces);
770 const SfxStringItem* pFieldResult = rReq.GetArg<SfxStringItem>(FN_PARAM_3);
771 if (pFieldResult)
773 // Allow specifying a field result / expanded value.
774 aFieldResult = pFieldResult->GetValue();
777 const SfxStringItem* pWrapper = rReq.GetArg<SfxStringItem>(FN_PARAM_4);
778 if (pWrapper)
780 // Wrap the fieldmark in the requested container instead of inserting it
781 // directly at the cursor position.
782 OUString aWrapper = pWrapper->GetValue();
783 if (aWrapper == "Footnote")
785 rSh.InsertFootnote(OUString());
787 else if (aWrapper == "Endnote")
789 // It's important that there is no Start/EndAction() around this, so the
790 // inner EndAction() triggers a layout update and the cursor can jump to the
791 // created SwFootnoteFrame.
792 rSh.InsertFootnote(OUString(), /*bEndNote=*/true);
796 // Don't update the layout after inserting content and before deleting temporary
797 // text nodes.
798 rSh.StartAction();
800 // Split node to remember where the start position is.
801 bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().SplitNode(
802 *pCursorPos->GetPoint(), false);
803 if(bSuccess)
805 SwPaM aFieldPam(*pCursorPos->GetPoint());
806 aFieldPam.Move(fnMoveBackward, GoInContent);
807 if (pFieldResult)
809 // Paste HTML content.
810 SwTranslateHelper::PasteHTMLToPaM(rSh, pCursorPos, aFieldResult.toUtf8(),
811 true);
812 if (pCursorPos->GetPoint()->GetContentIndex() == 0)
814 // The paste created a last empty text node, remove it.
815 SwPaM aPam(*pCursorPos->GetPoint());
816 aPam.SetMark();
817 aPam.Move(fnMoveBackward, GoInContent);
818 rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPam);
821 else
823 // Insert default placeholder.
824 rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos,
825 aFieldResult);
827 // Undo the above SplitNode().
828 aFieldPam.SetMark();
829 aFieldPam.Move(fnMoveForward, GoInContent);
830 rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aFieldPam);
831 *aFieldPam.GetMark() = *pCursorPos->GetPoint();
833 IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
834 sw::mark::IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
835 aFieldPam, OUString(), aFieldType, aFieldPam.Start());
836 if (pFieldmark && !aFieldCode.isEmpty())
838 pFieldmark->GetParameters()->insert(
839 std::pair<OUString, uno::Any>(ODF_CODE_PARAM, uno::Any(aFieldCode)));
842 rSh.EndAction();
845 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
846 rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
848 break;
849 case FN_INSERT_CHECKBOX_FORMFIELD:
851 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
853 SwPaM* pCursorPos = rSh.GetCursor();
854 if(pCursorPos)
856 IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
857 pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMCHECKBOX);
860 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
861 rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
863 break;
864 case FN_INSERT_DROPDOWN_FORMFIELD:
866 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
868 SwPaM* pCursorPos = rSh.GetCursor();
869 if(pCursorPos)
871 IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
872 pMarksAccess->makeNoTextFieldBookmark(*pCursorPos, OUString(), ODF_FORMDROPDOWN);
875 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
876 rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
878 break;
879 case FN_INSERT_DATE_FORMFIELD:
881 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
883 SwPaM* pCursorPos = rSh.GetCursor();
884 if(pCursorPos)
886 // Insert five enspaces into the text field so the field has extent
887 sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
888 bool bSuccess = rSh.GetDoc()->getIDocumentContentOperations().InsertString(*pCursorPos, OUString(vEnSpaces, ODF_FORMFIELD_DEFAULT_LENGTH));
889 if(bSuccess)
891 IDocumentMarkAccess* pMarksAccess = rSh.GetDoc()->getIDocumentMarkAccess();
892 SwPaM aFieldPam(pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex() - ODF_FORMFIELD_DEFAULT_LENGTH,
893 pCursorPos->GetPoint()->GetNode(), pCursorPos->GetPoint()->GetContentIndex());
894 sw::mark::IFieldmark* pFieldBM = pMarksAccess->makeFieldBookmark(aFieldPam, OUString(), ODF_FORMDATE,
895 aFieldPam.Start());
897 // Use a default date format and language
898 sw::mark::IFieldmark::parameter_map_t* pParameters = pFieldBM->GetParameters();
899 SvNumberFormatter* pFormatter = rSh.GetDoc()->GetNumberFormatter();
900 sal_uInt32 nStandardFormat = pFormatter->GetStandardFormat(SvNumFormatType::DATE);
901 const SvNumberformat* pFormat = pFormatter->GetEntry(nStandardFormat);
903 (*pParameters)[ODF_FORMDATE_DATEFORMAT] <<= pFormat->GetFormatstring();
904 (*pParameters)[ODF_FORMDATE_DATEFORMAT_LANGUAGE] <<= LanguageTag(pFormat->GetLanguage()).getBcp47();
908 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_FORM_FIELD, nullptr);
909 rSh.GetView().GetViewFrame().GetBindings().Invalidate( SID_UNDO );
911 break;
912 case FN_UPDATE_TEXT_FORMFIELDS:
914 // This updates multiple fieldmarks in a document, based on their field name & field command
915 // prefix.
916 OUString aFieldType;
917 const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
918 if (pFieldType)
920 aFieldType = pFieldType->GetValue();
922 OUString aFieldCommandPrefix;
923 const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
924 if (pFieldCommandPrefix)
926 aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
928 uno::Sequence<beans::PropertyValues> aFields;
929 const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
930 if (pFields)
932 pFields->GetValue() >>= aFields;
935 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr);
936 rSh.StartAction();
938 IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess();
939 sal_Int32 nFieldIndex = 0;
940 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
942 auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
943 assert(pFieldmark);
944 if (pFieldmark->GetFieldname() != aFieldType)
946 continue;
949 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
950 if (itParam == pFieldmark->GetParameters()->end())
952 continue;
955 OUString aCommand;
956 itParam->second >>= aCommand;
957 if (!aCommand.startsWith(aFieldCommandPrefix))
959 continue;
962 if (aFields.getLength() <= nFieldIndex)
964 continue;
967 comphelper::SequenceAsHashMap aMap(aFields[nFieldIndex++]);
968 itParam->second = aMap["FieldCommand"];
969 SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos());
970 aPaM.Normalize();
971 // Skip field start & separator.
972 aPaM.GetPoint()->AdjustContent(2);
973 // Skip field end.
974 aPaM.GetMark()->AdjustContent(-1);
975 rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM);
976 OUString aFieldResult;
977 aMap["FieldResult"] >>= aFieldResult;
978 SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8(), true);
981 rSh.EndAction();
982 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELDS, nullptr);
984 break;
985 case FN_DELETE_TEXT_FORMFIELDS:
987 // This deletes all fieldmarks that match the provided field type & field command prefix.
988 OUString aFieldType;
989 const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
990 if (pFieldType)
992 aFieldType = pFieldType->GetValue();
994 OUString aFieldCommandPrefix;
995 const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
996 if (pFieldCommandPrefix)
998 aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
1000 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr);
1001 rSh.StartAction();
1003 IDocumentMarkAccess* pMarkAccess = rSh.GetDoc()->getIDocumentMarkAccess();
1004 std::vector<sw::mark::IMark*> aRemovals;
1005 for (auto it = pMarkAccess->getFieldmarksBegin(); it != pMarkAccess->getFieldmarksEnd(); ++it)
1007 auto pFieldmark = dynamic_cast<sw::mark::IFieldmark*>(*it);
1008 assert(pFieldmark);
1009 if (pFieldmark->GetFieldname() != aFieldType)
1011 continue;
1014 if (!aFieldCommandPrefix.isEmpty())
1016 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
1017 if (itParam == pFieldmark->GetParameters()->end())
1019 continue;
1022 OUString aCommand;
1023 itParam->second >>= aCommand;
1024 if (!aCommand.startsWith(aFieldCommandPrefix))
1026 continue;
1030 aRemovals.push_back(pFieldmark);
1033 for (const auto& pMark : aRemovals)
1035 pMarkAccess->deleteMark(pMark);
1038 rSh.EndAction();
1039 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::DELETE_FORM_FIELDS, nullptr);
1041 break;
1042 case FN_PGNUMBER_WIZARD:
1044 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
1045 VclPtr<AbstractSwPageNumberDlg> pDlg(
1046 pFact->CreateSwPageNumberDlg(GetView().GetFrameWeld()));
1047 auto pShell = GetShellPtr();
1049 const SwPageDesc& rCurrDesc = rSh.GetPageDesc(rSh.GetCurPageDesc());
1050 pDlg->SetPageNumberType(rCurrDesc.GetNumType().GetNumberingType());
1052 pDlg->StartExecuteAsync([pShell, &rSh, pDlg](int nResult) {
1053 if ( nResult == RET_OK )
1055 auto rDoc = rSh.GetDoc();
1057 rSh.LockView(true);
1058 rSh.StartAllAction();
1059 rSh.SwCursorShell::Push();
1060 rDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr);
1062 const size_t nPageDescIndex = rSh.GetCurPageDesc();
1063 const SwPageDesc& rDesc = rSh.GetPageDesc(nPageDescIndex);
1064 const bool bHeader = !pDlg->GetPageNumberPosition();
1065 const bool bHeaderAlreadyOn = rDesc.GetMaster().GetHeader().IsActive();
1066 const bool bFooterAlreadyOn = rDesc.GetMaster().GetFooter().IsActive();
1067 const bool bIsSinglePage = rDesc.GetFollow() != &rDesc;
1068 const size_t nMirrorPagesNeeded = rDesc.IsFirstShared() ? 2 : 3;
1069 const OUString sBookmarkName = OUString::Concat("PageNumWizard_")
1070 + (bHeader ? "HEADER" : "FOOTER") + "_" + rDesc.GetName();
1071 IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess();
1073 // Allow wizard to be re-run: delete previously wizard-inserted page number.
1074 // Try before creating non-shared header: avoid copying ODD bookmark onto EVEN page.
1075 IDocumentMarkAccess::const_iterator_t ppMark = rIDMA.findMark(
1076 sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
1077 if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
1079 SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
1080 rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
1083 SwPageDesc aNewDesc(rDesc);
1084 bool bChangePageDesc = false;
1085 if (pDlg->GetPageNumberType() != aNewDesc.GetNumType().GetNumberingType())
1087 bChangePageDesc = true;
1088 SvxNumberType aNewType(rDesc.GetNumType());
1089 aNewType.SetNumberingType(pDlg->GetPageNumberType());
1090 aNewDesc.SetNumType(aNewType);
1093 // Insert header/footer
1094 if ((bHeader && !bHeaderAlreadyOn) || (!bHeader && !bFooterAlreadyOn))
1096 bChangePageDesc = true;
1097 SwFrameFormat &rMaster = aNewDesc.GetMaster();
1098 if (bHeader)
1099 rMaster.SetFormatAttr(SwFormatHeader(/*On=*/true));
1100 else
1101 rMaster.SetFormatAttr(SwFormatFooter(/*On=*/true));
1103 // Init copied from ChangeHeaderOrFooter: keep in sync
1104 constexpr tools::Long constTwips_5mm = o3tl::toTwips(5, o3tl::Length::mm);
1105 const SvxULSpaceItem aUL(bHeader ? 0 : constTwips_5mm,
1106 bHeader ? constTwips_5mm : 0,
1107 RES_UL_SPACE);
1108 const XFillStyleItem aFill(drawing::FillStyle_NONE);
1109 SwFrameFormat& rFormat
1110 = bHeader
1111 ? const_cast<SwFrameFormat&>(*rMaster.GetHeader().GetHeaderFormat())
1112 : const_cast<SwFrameFormat&>(*rMaster.GetFooter().GetFooterFormat());
1113 rFormat.SetFormatAttr(aUL);
1114 rFormat.SetFormatAttr(aFill);
1116 // Might as well turn on margin mirroring too - if appropriate
1117 if (pDlg->GetMirrorOnEvenPages() && !bHeaderAlreadyOn && !bFooterAlreadyOn
1118 && !bIsSinglePage
1119 && (aNewDesc.ReadUseOn() & UseOnPage::Mirror) == UseOnPage::All)
1121 aNewDesc.WriteUseOn(rDesc.ReadUseOn() | UseOnPage::Mirror);
1125 const bool bCreateMirror = !bIsSinglePage && pDlg->GetMirrorOnEvenPages()
1126 && nMirrorPagesNeeded <= rSh.GetPageCnt();
1127 if (bCreateMirror)
1129 // Use different left/right header/footer
1130 if ((bHeader && rDesc.IsHeaderShared()) || (!bHeader && rDesc.IsFooterShared()))
1132 bChangePageDesc = true;
1133 if (bHeader)
1134 aNewDesc.ChgHeaderShare(/*Share=*/false);
1135 else
1136 aNewDesc.ChgFooterShare(/*Share=*/false);
1140 if (bChangePageDesc)
1141 rSh.ChgPageDesc(nPageDescIndex, aNewDesc);
1143 // Go to the header or footer insert position
1144 bool bInHF = false;
1145 bool bSkipMirror = true;
1146 size_t nEvenPage = 0;
1147 if (bCreateMirror || !rSh.GetCurrFrame())
1149 // Come here if Currframe can't be found, otherwise Goto*Text will crash.
1150 // Get*PageNum will also be invalid (0), so we have no idea where we are.
1151 // (Since not asking for mirror, the likelihood is that the bHeader is shared,
1152 // in which case it doesn't matter anyway, and we just hope for the best.)
1153 // Read the code in this block assuming that bCreateMirror is true.
1155 // There are enough pages that there probably is a valid odd page.
1156 // However, that is not guaranteed: perhaps the page style switched,
1157 // or a blank page was forced, or some other complexity.
1158 bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true);
1159 if (bInHF)
1161 // Remember valid EVEN page. Mirror it if also a valid ODD or FIRST page
1162 nEvenPage = rSh.GetVirtPageNum();
1163 assert (nEvenPage && "couldn't find page number. Use a bool instead");
1166 bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/false);
1167 if (bInHF && nEvenPage)
1169 // Even though the cursor may be on a FIRST page,
1170 // the user requested mirrored pages, and we have both ODD and EVEN,
1171 // so set page numbers on these two pages, and leave FIRST alone.
1172 bSkipMirror = false;
1174 if (!bInHF)
1176 // no ODD page, look for FIRST page
1177 bInHF = rSh.SetCursorInHdFt(nPageDescIndex, bHeader, false, /*First=*/true);
1178 if (bInHF && nEvenPage)
1180 // Unlikely but valid situation: EVEN and FIRST pages, but no ODD page.
1181 // In this case, the first header gets the specified page number
1182 // and the even header is mirrored, with an empty odd header,
1183 // as the user (somewhat) requested.
1184 bSkipMirror = false;
1187 assert((bInHF || nEvenPage) && "Impossible - why couldn't the move happen?");
1188 assert((bInHF || nEvenPage == rSh.GetVirtPageNum()) && "Unexpected move");
1190 else
1192 if (bHeader)
1193 bInHF = rSh.GotoHeaderText();
1194 else
1195 bInHF = rSh.GotoFooterText();
1196 assert(bInHF && "shouldn't have a problem going to text when no mirroring");
1199 // Allow wizard to be re-run: delete previously wizard-inserted page number.
1200 // Now that the cursor may have moved to a different page, try delete again.
1201 ppMark = rIDMA.findMark(sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
1202 if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
1204 SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
1205 rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
1208 SwTextNode* pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode();
1210 // Insert new line if there is already text in header/footer
1211 if (pTextNode && !pTextNode->GetText().isEmpty())
1213 rDoc->getIDocumentContentOperations().SplitNode(*rSh.GetCursor()->GetPoint(), false);
1215 // Go back to start of header/footer
1216 if (bHeader)
1217 rSh.GotoHeaderText();
1218 else
1219 rSh.GotoFooterText();
1222 // Set alignment for the new line
1223 switch (pDlg->GetPageNumberAlignment())
1225 case 0:
1227 SvxAdjustItem aAdjustItem(SvxAdjust::Left, RES_PARATR_ADJUST);
1228 rSh.SetAttrItem(aAdjustItem);
1229 break;
1231 case 1:
1233 SvxAdjustItem aAdjustItem(SvxAdjust::Center, RES_PARATR_ADJUST);
1234 rSh.SetAttrItem(aAdjustItem);
1235 break;
1237 case 2:
1239 SvxAdjustItem aAdjustItem(SvxAdjust::Right, RES_PARATR_ADJUST);
1240 rSh.SetAttrItem(aAdjustItem);
1241 break;
1245 sal_Int32 nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex();
1246 assert(!nStartContentIndex && "earlier split node if not empty, but not zero?");
1248 // Insert page number
1249 SwFieldMgr aMgr(pShell);
1250 SwInsertField_Data aData(SwFieldTypesEnum::PageNumber, 0,
1251 OUString(), OUString(), SVX_NUM_PAGEDESC);
1252 aMgr.InsertField(aData);
1253 if (pDlg->GetIncludePageTotal())
1255 rDoc->getIDocumentContentOperations().InsertString(*rSh.GetCursor(), " / ");
1256 SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics, DS_PAGE,
1257 OUString(), OUString(), SVX_NUM_PAGEDESC);
1258 aMgr.InsertField(aPageTotalData);
1261 // Mark inserted fields with a bookmark - so it can be found/removed if re-run
1262 SwPaM aNewBookmarkPaM(*rSh.GetCursor()->Start());
1263 aNewBookmarkPaM.SetMark();
1264 assert(aNewBookmarkPaM.GetPointContentNode() && "only SetContent on content node");
1265 aNewBookmarkPaM.Start()->SetContent(nStartContentIndex);
1266 rIDMA.makeMark(aNewBookmarkPaM,
1267 sBookmarkName + OUString::number(rSh.GetVirtPageNum()),
1268 IDocumentMarkAccess::MarkType::BOOKMARK,
1269 sw::mark::InsertMode::New);
1271 // Mirror on the even pages
1272 if (!bSkipMirror && bCreateMirror
1273 && rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true))
1275 assert(nEvenPage && "what? no even page and yet we got here?");
1276 ppMark = rIDMA.findMark(sBookmarkName + OUString::number(rSh.GetVirtPageNum()));
1277 if (ppMark != rIDMA.getAllMarksEnd() && *ppMark)
1279 SwPaM aDeleteOldPageNum((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
1280 rDoc->getIDocumentContentOperations().DeleteAndJoin(aDeleteOldPageNum);
1283 pTextNode = rSh.GetCursor()->GetPoint()->GetNode().GetTextNode();
1285 // Insert new line if there is already text in header/footer
1286 if (pTextNode && !pTextNode->GetText().isEmpty())
1288 rDoc->getIDocumentContentOperations().SplitNode(
1289 *rSh.GetCursor()->GetPoint(), false);
1290 // Go back to start of header/footer
1291 rSh.SetCursorInHdFt(nPageDescIndex, bHeader, /*Even=*/true);
1294 // mirror the adjustment
1295 assert(pDlg->GetPageNumberAlignment() != 1 && "cannot have Center and bMirror");
1296 SvxAdjust eAdjust = SvxAdjust::Left;
1297 if (!pDlg->GetPageNumberAlignment())
1298 eAdjust = SvxAdjust::Right;
1299 SvxAdjustItem aMirrorAdjustItem(eAdjust, RES_PARATR_ADJUST);
1300 rSh.SetAttrItem(aMirrorAdjustItem);
1302 nStartContentIndex = rSh.GetCursor()->Start()->GetContentIndex();
1304 // Insert page number
1305 SwFieldMgr aEvenMgr(pShell);
1306 aEvenMgr.InsertField(aData);
1307 if (pDlg->GetIncludePageTotal())
1309 rDoc->getIDocumentContentOperations().InsertString(*rSh.GetCursor(), " / ");
1310 SwInsertField_Data aPageTotalData(SwFieldTypesEnum::DocumentStatistics,
1311 DS_PAGE, OUString(), OUString(),
1312 SVX_NUM_PAGEDESC);
1313 aMgr.InsertField(aPageTotalData);
1316 // Mark inserted fields with a bookmark - so it can be found/removed if re-run
1317 SwPaM aNewEvenBookmarkPaM(*rSh.GetCursor()->Start());
1318 aNewEvenBookmarkPaM.SetMark();
1319 aNewEvenBookmarkPaM.Start()->SetContent(nStartContentIndex);
1320 rIDMA.makeMark(aNewEvenBookmarkPaM,
1321 sBookmarkName + OUString::number(rSh.GetVirtPageNum()),
1322 IDocumentMarkAccess::MarkType::BOOKMARK,
1323 sw::mark::InsertMode::New);
1326 rSh.SwCursorShell::Pop(SwCursorShell::PopMode::DeleteCurrent);
1327 rSh.EndAllAction();
1328 rSh.LockView(false);
1329 rDoc->GetIDocumentUndoRedo().EndUndo(SwUndoId::INSERT_PAGE_NUMBER, nullptr);
1331 pDlg->disposeOnce();
1333 rReq.Done();
1335 break;
1336 case FN_UPDATE_TEXT_FORMFIELD:
1338 // This updates a single fieldmark under the current cursor.
1339 OUString aFieldType;
1340 const SfxStringItem* pFieldType = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1341 if (pFieldType)
1343 aFieldType = pFieldType->GetValue();
1345 OUString aFieldCommandPrefix;
1346 const SfxStringItem* pFieldCommandPrefix = rReq.GetArg<SfxStringItem>(FN_PARAM_2);
1347 if (pFieldCommandPrefix)
1349 aFieldCommandPrefix = pFieldCommandPrefix->GetValue();
1351 uno::Sequence<beans::PropertyValue> aField;
1352 const SfxUnoAnyItem* pFields = rReq.GetArg<SfxUnoAnyItem>(FN_PARAM_3);
1353 if (pFields)
1355 pFields->GetValue() >>= aField;
1358 IDocumentMarkAccess& rIDMA = *rSh.getIDocumentMarkAccess();
1359 SwPosition& rCursor = *rSh.GetCursor()->GetPoint();
1360 sw::mark::IFieldmark* pFieldmark = rIDMA.getInnerFieldmarkFor(rCursor);
1361 if (!pFieldmark)
1363 break;
1366 if (pFieldmark->GetFieldname() != aFieldType)
1368 break;
1371 auto itParam = pFieldmark->GetParameters()->find(ODF_CODE_PARAM);
1372 if (itParam == pFieldmark->GetParameters()->end())
1374 break;
1377 OUString aCommand;
1378 itParam->second >>= aCommand;
1379 if (!aCommand.startsWith(aFieldCommandPrefix))
1381 break;
1384 rSh.GetDoc()->GetIDocumentUndoRedo().StartUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr);
1385 rSh.StartAction();
1386 comphelper::SequenceAsHashMap aMap(aField);
1387 itParam->second = aMap["FieldCommand"];
1388 SwPaM aPaM(pFieldmark->GetMarkPos(), pFieldmark->GetOtherMarkPos());
1389 aPaM.Normalize();
1390 // Skip field start & separator.
1391 aPaM.GetPoint()->AdjustContent(2);
1392 // Skip field end.
1393 aPaM.GetMark()->AdjustContent(-1);
1394 rSh.GetDoc()->getIDocumentContentOperations().DeleteAndJoin(aPaM);
1395 OUString aFieldResult;
1396 aMap["FieldResult"] >>= aFieldResult;
1397 SwTranslateHelper::PasteHTMLToPaM(rSh, &aPaM, aFieldResult.toUtf8(), true);
1399 rSh.EndAction();
1400 rSh.GetDoc()->GetIDocumentUndoRedo().EndUndo(SwUndoId::UPDATE_FORM_FIELD, nullptr);
1402 break;
1403 default:
1404 OSL_FAIL("wrong dispatcher");
1405 return;
1409 void SwTextShell::StateField( SfxItemSet &rSet )
1411 SwWrtShell& rSh = GetShell();
1412 SfxWhichIter aIter( rSet );
1413 const SwField* pField = nullptr;
1414 bool bGetField = false;
1415 sal_uInt16 nWhich = aIter.FirstWhich();
1417 while (nWhich)
1419 switch (nWhich)
1421 case FN_DELETE_COMMENT:
1422 case FN_DELETE_NOTE_AUTHOR:
1423 case FN_DELETE_ALL_NOTES:
1424 case FN_FORMAT_ALL_NOTES:
1425 case FN_HIDE_NOTE:
1426 case FN_HIDE_NOTE_AUTHOR:
1427 case FN_HIDE_ALL_NOTES:
1429 SwPostItMgr* pPostItMgr = GetView().GetPostItMgr();
1430 if ( !pPostItMgr )
1431 rSet.InvalidateItem( nWhich );
1432 else if ( !pPostItMgr->HasActiveSidebarWin() )
1434 rSet.InvalidateItem( FN_DELETE_COMMENT );
1435 rSet.InvalidateItem( FN_HIDE_NOTE );
1437 // tdf#137568 do not offer comment formatting, if no comments are present
1438 if (!pPostItMgr || !pPostItMgr->HasNotes())
1439 rSet.DisableItem( FN_FORMAT_ALL_NOTES );
1441 break;
1443 case FN_EDIT_FIELD:
1445 if( !bGetField )
1447 pField = rSh.GetCurField(true);
1448 bGetField = true;
1451 SwFieldIds nTempWhich = pField ? pField->GetTyp()->Which() : SwFieldIds::Unknown;
1452 if( SwFieldIds::Unknown == nTempWhich ||
1453 SwFieldIds::Postit == nTempWhich ||
1454 SwFieldIds::Script == nTempWhich ||
1455 SwFieldIds::TableOfAuthorities == nTempWhich )
1456 rSet.DisableItem( nWhich );
1457 else if( SwFieldIds::Dde == nTempWhich &&
1458 !static_cast<SwDDEFieldType*>(pField->GetTyp())->GetBaseLink().IsVisible())
1460 // nested links cannot be edited
1461 rSet.DisableItem( nWhich );
1464 break;
1466 case FN_UPDATE_SEL_FIELD:
1468 pField = rSh.GetCurField();
1470 if (!pField)
1471 rSet.DisableItem( nWhich );
1474 break;
1476 case FN_EXECUTE_MACROFIELD:
1478 if(!bGetField)
1480 pField = rSh.GetCurField();
1481 bGetField = true;
1483 if(!pField || pField->GetTyp()->Which() != SwFieldIds::Macro)
1484 rSet.DisableItem(nWhich);
1486 break;
1488 case FN_INSERT_FIELD:
1490 if ( rSh.CursorInsideInputField() )
1492 rSet.DisableItem(nWhich);
1494 else
1496 SfxViewFrame& rVFrame = GetView().GetViewFrame();
1497 //#i5788# prevent closing of the field dialog while a modal dialog ( Input field dialog ) is active
1498 if(!rVFrame.IsInModalMode() &&
1499 rVFrame.KnowsChildWindow(FN_INSERT_FIELD) && !rVFrame.HasChildWindow(FN_INSERT_FIELD_DATA_ONLY) )
1500 rSet.Put(SfxBoolItem( FN_INSERT_FIELD, rVFrame.HasChildWindow(nWhich)));
1501 else
1502 rSet.DisableItem(FN_INSERT_FIELD);
1505 break;
1507 case FN_INSERT_REF_FIELD:
1509 SfxViewFrame& rVFrame = GetView().GetViewFrame();
1510 if ( !rVFrame.KnowsChildWindow(FN_INSERT_FIELD)
1511 || rSh.CursorInsideInputField() )
1513 rSet.DisableItem(FN_INSERT_REF_FIELD);
1516 break;
1518 case FN_INSERT_FIELD_CTRL:
1519 if ( rSh.CursorInsideInputField() )
1521 rSet.DisableItem(nWhich);
1523 else
1525 rSet.Put(SfxBoolItem( nWhich, GetView().GetViewFrame().HasChildWindow(FN_INSERT_FIELD)));
1527 break;
1529 case FN_REDLINE_COMMENT:
1530 if (!comphelper::LibreOfficeKit::isActive() && !rSh.GetCurrRedline())
1531 rSet.DisableItem(nWhich);
1532 break;
1534 case FN_REPLY:
1535 if (!comphelper::LibreOfficeKit::isActive())
1536 rSet.DisableItem(nWhich);
1537 break;
1539 case FN_POSTIT :
1540 case FN_JAVAEDIT :
1542 bool bCurField = false;
1543 pField = rSh.GetCurField();
1544 if(nWhich == FN_POSTIT)
1545 bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Postit;
1546 else
1547 bCurField = pField && pField->GetTyp()->Which() == SwFieldIds::Script;
1549 if( !bCurField && rSh.IsReadOnlyAvailable() && rSh.HasReadonlySel() )
1551 rSet.DisableItem(nWhich);
1553 else if ( rSh.CursorInsideInputField() )
1555 rSet.DisableItem(nWhich);
1557 // tdf#86188, tdf#135794: Allow disabling comment insertion
1558 // on footnote/endnote/header/frames for better OOXML interoperability
1559 else if (!officecfg::Office::Compatibility::View::AllowCommentsInFootnotes::get() &&
1560 (rSh.IsCursorInFootnote() || rSh.IsInHeaderFooter() ||
1561 rSh.GetCurrFlyFrame(/*bCalcFrame=*/false)))
1563 rSet.DisableItem(nWhich);
1567 break;
1569 case FN_INSERT_FLD_AUTHOR:
1570 case FN_INSERT_FLD_DATE:
1571 case FN_INSERT_FLD_PGCOUNT:
1572 case FN_INSERT_FLD_PGNUMBER:
1573 case FN_INSERT_FLD_TIME:
1574 case FN_INSERT_FLD_TITLE:
1575 case FN_INSERT_FLD_TOPIC:
1576 case FN_INSERT_DBFIELD:
1577 if ( rSh.CursorInsideInputField() )
1579 rSet.DisableItem(nWhich);
1581 break;
1583 case FN_INSERT_TEXT_FORMFIELD:
1584 case FN_INSERT_CHECKBOX_FORMFIELD:
1585 case FN_INSERT_DROPDOWN_FORMFIELD:
1586 case FN_INSERT_DATE_FORMFIELD:
1587 if ( rSh.CursorInsideInputField() )
1589 rSet.DisableItem(nWhich);
1591 else
1593 // Check whether we are in a text form field
1594 SwPosition aCursorPos(*rSh.GetCursor()->GetPoint());
1595 sw::mark::IFieldmark* pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aCursorPos);
1596 if ((!pFieldBM || pFieldBM->GetFieldname() != ODF_FORMTEXT)
1597 && aCursorPos.GetContentIndex() > 0)
1599 SwPosition aPos(*aCursorPos.GetContentNode(), aCursorPos.GetContentIndex() - 1);
1600 pFieldBM = GetShell().getIDocumentMarkAccess()->getInnerFieldmarkFor(aPos);
1602 if (pFieldBM && pFieldBM->GetFieldname() == ODF_FORMTEXT &&
1603 (aCursorPos > pFieldBM->GetMarkStart() && aCursorPos < pFieldBM->GetMarkEnd() ))
1605 rSet.DisableItem(nWhich);
1608 break;
1611 nWhich = aIter.NextWhich();
1615 void SwTextShell::InsertHyperlink(const SvxHyperlinkItem& rHlnkItem)
1617 const OUString& rName = rHlnkItem.GetName();
1618 const OUString& rURL = rHlnkItem.GetURL();
1619 const OUString& rTarget = rHlnkItem.GetTargetFrame();
1620 const OUString& rReplacementText = rHlnkItem.GetReplacementText();
1621 sal_uInt16 nType = o3tl::narrowing<sal_uInt16>(rHlnkItem.GetInsertMode());
1622 nType &= ~HLINK_HTMLMODE;
1623 const SvxMacroTableDtor* pMacroTable = rHlnkItem.GetMacroTable();
1625 SwWrtShell& rSh = GetShell();
1627 if( !(rSh.GetSelectionType() & SelectionType::Text) )
1628 return;
1630 rSh.StartAction();
1631 SfxItemSetFixed<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT> aSet(GetPool());
1632 rSh.GetCurAttr( aSet );
1634 if(SfxItemState::SET == aSet.GetItemState(RES_TXTATR_INETFMT, false))
1636 // Select links
1637 rSh.SwCursorShell::SelectTextAttr(RES_TXTATR_INETFMT, false);
1639 switch (nType)
1641 case HLINK_DEFAULT:
1642 case HLINK_FIELD:
1644 SwFormatINetFormat aINetFormat( rURL, rTarget );
1645 aINetFormat.SetName(rHlnkItem.GetIntName());
1646 if(pMacroTable)
1648 const SvxMacro *pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOver );
1649 if( pMacro )
1650 aINetFormat.SetMacro(SvMacroItemId::OnMouseOver, *pMacro);
1651 pMacro = pMacroTable->Get( SvMacroItemId::OnClick );
1652 if( pMacro )
1653 aINetFormat.SetMacro(SvMacroItemId::OnClick, *pMacro);
1654 pMacro = pMacroTable->Get( SvMacroItemId::OnMouseOut );
1655 if( pMacro )
1656 aINetFormat.SetMacro(SvMacroItemId::OnMouseOut, *pMacro);
1658 rSh.SttSelect();
1659 // inserting mention
1660 if (comphelper::LibreOfficeKit::isActive() && !rReplacementText.isEmpty())
1662 SwPaM* pCursorPos = rSh.GetCursor();
1663 // move cursor backwards to select @mention
1664 for(int i=0; i < rReplacementText.getLength(); i++)
1665 pCursorPos->Move(fnMoveBackward);
1666 rSh.InsertURL( aINetFormat, rName, false );
1668 else
1670 rSh.InsertURL( aINetFormat, rName, true );
1672 rSh.EndSelect();
1674 break;
1676 case HLINK_BUTTON:
1677 bool bSel = rSh.HasSelection();
1678 if(bSel)
1679 rSh.DelRight();
1680 InsertURLButton( rURL, rTarget, rName );
1681 rSh.EnterStdMode();
1682 break;
1684 rSh.EndAction();
1687 IMPL_LINK( SwTextShell, RedlineNextHdl, AbstractSvxPostItDialog&, rDlg, void )
1689 SwWrtShell* pSh = GetShellPtr();
1691 // Insert or change a comment.
1692 pSh->SetRedlineComment(rDlg.GetNote());
1694 const SwRangeRedline *pRedline = pSh->GetCurrRedline();
1696 if (!pRedline)
1697 return;
1699 // Traveling only if more than one field.
1700 if( !pSh->IsCursorPtAtEnd() )
1701 pSh->SwapPam(); // Move the cursor behind the Redline.
1703 pSh->Push();
1704 const SwRangeRedline *pActRed = pSh->SelNextRedline();
1705 pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent);
1707 bool bEnable = false;
1709 if (pActRed)
1711 pSh->StartAction();
1712 pSh->Push();
1713 bEnable = pSh->SelNextRedline() != nullptr;
1714 pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
1715 pSh->EndAction();
1718 rDlg.EnableTravel(bEnable, true);
1720 if( pSh->IsCursorPtAtEnd() )
1721 pSh->SwapPam();
1723 pRedline = pSh->GetCurrRedline();
1724 OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
1726 rDlg.SetNote(sComment);
1727 rDlg.ShowLastAuthor( pRedline->GetAuthorString(),
1728 GetAppLangDateTimeString(
1729 pRedline->GetRedlineData().GetTimeStamp() ));
1731 rDlg.SetText(lcl_BuildTitleWithRedline(pRedline));
1735 IMPL_LINK( SwTextShell, RedlinePrevHdl, AbstractSvxPostItDialog&, rDlg, void )
1737 SwWrtShell* pSh = GetShellPtr();
1739 // Insert or change a comment.
1740 pSh->SetRedlineComment(rDlg.GetNote());
1742 const SwRangeRedline *pRedline = pSh->GetCurrRedline();
1744 if (!pRedline)
1745 return;
1747 // Traveling only if more than one field.
1748 pSh->Push();
1749 const SwRangeRedline *pActRed = pSh->SelPrevRedline();
1750 pSh->Pop((pActRed != nullptr) ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent);
1752 bool bEnable = false;
1754 if (pActRed)
1756 pSh->StartAction();
1757 pSh->Push();
1758 bEnable = pSh->SelPrevRedline() != nullptr;
1759 pSh->Pop(SwCursorShell::PopMode::DeleteCurrent);
1760 pSh->EndAction();
1763 rDlg.EnableTravel(true, bEnable);
1765 pRedline = pSh->GetCurrRedline();
1766 OUString sComment = convertLineEnd(pRedline->GetComment(), GetSystemLineEnd());
1768 rDlg.SetNote(sComment);
1769 rDlg.ShowLastAuthor(pRedline->GetAuthorString(),
1770 GetAppLangDateTimeString(
1771 pRedline->GetRedlineData().GetTimeStamp() ));
1773 rDlg.SetText(lcl_BuildTitleWithRedline(pRedline));
1777 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */