Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / ui / fldui / fldref.cxx
blob54f9c9fc98dc0a27b8da9bd5980cb8cf919d2edb
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 <swtypes.hxx>
21 #include <IMark.hxx>
22 #include <expfld.hxx>
23 #include <swmodule.hxx>
24 #include "fldref.hxx"
25 #include <frmatr.hxx>
26 #include <reffld.hxx>
27 #include <wrtsh.hxx>
29 #include <fldref.hrc>
30 #include <strings.hrc>
31 #include <SwNodeNum.hxx>
32 #include <IDocumentMarkAccess.hxx>
33 #include <unotools/syslocaleoptions.hxx>
34 #include <unotools/charclass.hxx>
35 #include <osl/diagnose.h>
37 #include <comphelper/string.hxx>
38 #include <editeng/frmdiritem.hxx>
39 #include <o3tl/safeint.hxx>
40 #include <o3tl/string_view.hxx>
41 #include <vcl/settings.hxx>
43 #define REFFLDFLAG 0x4000
44 #define REFFLDFLAG_BOOKMARK 0x4800
45 #define REFFLDFLAG_FOOTNOTE 0x5000
46 #define REFFLDFLAG_ENDNOTE 0x6000
47 // #i83479#
48 #define REFFLDFLAG_HEADING 0x7100
49 #define REFFLDFLAG_NUMITEM 0x7200
51 static sal_uInt16 nFieldDlgFormatSel = 0;
53 #define USER_DATA_VERSION_1 "1"
54 #define USER_DATA_VERSION USER_DATA_VERSION_1
56 SwFieldRefPage::SwFieldRefPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet )
57 : SwFieldPage(pPage, pController, "modules/swriter/ui/fldrefpage.ui", "FieldRefPage", pCoreSet)
58 , mpSavedSelectedTextNode(nullptr)
59 , mnSavedSelectedPos(0)
60 , m_xTypeLB(m_xBuilder->weld_tree_view("type"))
61 , m_xSelection(m_xBuilder->weld_widget("selectframe"))
62 , m_xSelectionLB(m_xBuilder->weld_tree_view("select"))
63 , m_xSelectionToolTipLB(m_xBuilder->weld_tree_view("selecttip"))
64 , m_xFormat(m_xBuilder->weld_widget("formatframe"))
65 , m_xFormatLB(m_xBuilder->weld_tree_view("format"))
66 , m_xNameFT(m_xBuilder->weld_label("nameft"))
67 , m_xNameED(m_xBuilder->weld_entry("name"))
68 , m_xValueED(m_xBuilder->weld_entry("value"))
69 , m_xFilterED(m_xBuilder->weld_entry("filter"))
71 m_xSelectionLB->make_sorted();
72 // #i83479#
73 for (auto const& aID : FLD_REF_PAGE_TYPES)
75 m_xTypeLB->append_text(SwResId(aID));
76 m_xFormatLB->append_text(SwResId(aID));
79 m_sBookmarkText = m_xTypeLB->get_text(0);
80 m_sFootnoteText = m_xTypeLB->get_text(1);
81 m_sEndnoteText = m_xTypeLB->get_text(2);
82 // #i83479#
83 m_sHeadingText = m_xTypeLB->get_text(3);
84 m_sNumItemText = m_xTypeLB->get_text(4);
86 auto nHeight = m_xTypeLB->get_height_rows(8);
87 auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH;
88 m_xTypeLB->set_size_request(nWidth * 1.33, nHeight);
89 m_xFormatLB->set_size_request(nWidth * 1.33, nHeight);
90 m_xSelection->set_size_request(nWidth * 2, nHeight);
91 nHeight = m_xTypeLB->get_height_rows(8);
92 m_xSelectionToolTipLB->set_size_request(nHeight, nWidth*2);
94 m_xTypeLB->clear();
96 m_xNameED->connect_changed(LINK(this, SwFieldRefPage, ModifyHdl));
97 m_xFilterED->connect_changed( LINK( this, SwFieldRefPage, ModifyHdl_Impl ) );
99 m_xTypeLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl));
100 m_xTypeLB->connect_changed(LINK(this, SwFieldRefPage, TypeHdl));
101 m_xSelectionLB->connect_changed(LINK(this, SwFieldRefPage, SubTypeListBoxHdl));
102 m_xSelectionLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl));
103 m_xFormatLB->connect_row_activated(LINK(this, SwFieldRefPage, TreeViewInsertHdl));
105 // #i83479#
106 m_xSelectionToolTipLB->connect_changed( LINK(this, SwFieldRefPage, SubTypeTreeListBoxHdl) );
107 m_xSelectionToolTipLB->connect_row_activated( LINK(this, SwFieldRefPage, TreeViewInsertHdl) );
108 m_xFilterED->grab_focus();
110 // uitests
111 m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-ref");
112 m_xNameED->set_buildable_name(m_xNameED->get_buildable_name() + "-ref");
113 m_xValueED->set_buildable_name(m_xValueED->get_buildable_name() + "-ref");
114 m_xSelectionLB->set_buildable_name(m_xSelectionLB->get_buildable_name() + "-ref");
115 m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-ref");
118 SwFieldRefPage::~SwFieldRefPage()
122 IMPL_LINK_NOARG(SwFieldRefPage, ModifyHdl_Impl, weld::Entry&, void)
124 UpdateSubType(comphelper::string::strip(m_xFilterED->get_text(), ' '));
125 // tdf#135938 - refresh cross-reference name after filter selection has changed
126 SubTypeHdl();
129 // #i83479#
130 void SwFieldRefPage::SaveSelectedTextNode()
132 mpSavedSelectedTextNode = nullptr;
133 mnSavedSelectedPos = 0;
134 if ( !m_xSelectionToolTipLB->get_visible() )
135 return;
137 int nEntry = m_xSelectionToolTipLB->get_selected_index();
138 if (nEntry == -1)
139 return;
141 const sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
143 if ( nTypeId == REFFLDFLAG_HEADING )
145 mnSavedSelectedPos = m_xSelectionToolTipLB->get_id(nEntry).toUInt32();
146 if ( mnSavedSelectedPos < maOutlineNodes.size() )
148 mpSavedSelectedTextNode = maOutlineNodes[mnSavedSelectedPos];
151 else if ( nTypeId == REFFLDFLAG_NUMITEM )
153 mnSavedSelectedPos = m_xSelectionToolTipLB->get_id(nEntry).toUInt32();
154 if ( mnSavedSelectedPos < maNumItems.size() )
156 mpSavedSelectedTextNode = maNumItems[mnSavedSelectedPos]->GetTextNode();
161 void SwFieldRefPage::Reset(const SfxItemSet* )
163 if (!IsFieldEdit())
165 SavePos(*m_xTypeLB);
166 // #i83479#
167 SaveSelectedTextNode();
169 SetSelectionSel(-1);
170 SetTypeSel(-1);
171 Init(); // general initialisation
173 // initialise TypeListBox
174 m_xTypeLB->freeze();
175 m_xTypeLB->clear();
177 // fill Type-Listbox
179 // set/insert reference
180 const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup());
182 for (short i = rRg.nStart; i < rRg.nEnd; ++i)
184 const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i);
186 if (!IsFieldEdit() || nTypeId != SwFieldTypesEnum::SetRef)
188 m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i));
192 // #i83479#
193 // entries for headings and numbered items
194 m_xTypeLB->append(OUString::number(REFFLDFLAG_HEADING), m_sHeadingText);
195 m_xTypeLB->append(OUString::number(REFFLDFLAG_NUMITEM), m_sNumItemText);
197 // fill up with the sequence types
198 SwWrtShell *pSh = GetWrtShell();
199 if (!pSh)
200 pSh = ::GetActiveWrtShell();
201 if (!pSh)
202 return;
204 // tdf#148432 in LTR UI override the navigator treeview direction based on
205 // the first page directionality
206 if (!AllSettings::GetLayoutRTL())
208 const SwPageDesc& rDesc = pSh->GetPageDesc(0);
209 const SvxFrameDirectionItem& rFrameDir = rDesc.GetMaster().GetFrameDir();
210 m_xSelectionToolTipLB->set_direction(rFrameDir.GetValue() == SvxFrameDirection::Horizontal_RL_TB);
213 const size_t nFieldTypeCnt = pSh->GetFieldTypeCount(SwFieldIds::SetExp);
215 OSL_ENSURE( nFieldTypeCnt < o3tl::make_unsigned(REFFLDFLAG), "<SwFieldRefPage::Reset> - Item index will overlap flags!" );
217 for (size_t n = 0; n < nFieldTypeCnt; ++n)
219 SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType(n, SwFieldIds::SetExp));
221 if ((nsSwGetSetExpType::GSE_SEQ & pType->GetType()) && pType->HasWriterListeners() && pSh->IsUsed(*pType))
223 m_xTypeLB->append(OUString::number(REFFLDFLAG | n), pType->GetName());
227 // text marks - now always (because of globaldocuments)
228 m_xTypeLB->append(OUString::number(REFFLDFLAG_BOOKMARK), m_sBookmarkText);
230 // footnotes:
231 if( pSh->HasFootnotes() )
233 m_xTypeLB->append(OUString::number(REFFLDFLAG_FOOTNOTE), m_sFootnoteText);
236 // endnotes:
237 if ( pSh->HasFootnotes(true) )
239 m_xTypeLB->append(OUString::number(REFFLDFLAG_ENDNOTE), m_sEndnoteText);
242 m_xTypeLB->thaw();
244 // select old Pos
245 if (!IsFieldEdit())
246 RestorePos(*m_xTypeLB);
248 nFieldDlgFormatSel = 0;
250 sal_uInt16 nFormatBoxPosition = USHRT_MAX;
251 if( !IsRefresh() )
253 sal_Int32 nIdx{ 0 };
254 const OUString sUserData = GetUserData();
255 if(!IsRefresh() && o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx),
256 u"" USER_DATA_VERSION_1))
258 const sal_uInt16 nVal = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx)));
259 if(nVal != USHRT_MAX)
261 for(sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; ++i)
263 if (nVal == m_xTypeLB->get_id(i).toUInt32())
265 m_xTypeLB->select(i);
266 break;
269 if (nIdx>=0 && nIdx<sUserData.getLength())
271 nFormatBoxPosition = static_cast< sal_uInt16 >(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx)));
276 TypeHdl(*m_xTypeLB);
277 if (nFormatBoxPosition < m_xFormatLB->n_children())
279 m_xFormatLB->select(nFormatBoxPosition);
281 if (IsFieldEdit())
283 m_xTypeLB->save_value();
284 m_xSelectionLB->save_value();
285 m_xFormatLB->save_value();
286 m_xNameED->save_value();
287 m_xValueED->save_value();
288 m_xFilterED->set_text(OUString());
292 IMPL_LINK_NOARG(SwFieldRefPage, TypeHdl, weld::TreeView&, void)
294 // save old ListBoxPos
295 const sal_Int32 nOld = GetTypeSel();
297 // current ListBoxPos
298 SetTypeSel(m_xTypeLB->get_selected_index());
300 if(GetTypeSel() == -1)
302 if (IsFieldEdit())
304 // select positions
305 OUString sName;
306 sal_uInt16 nFlag = 0;
308 switch( GetCurField()->GetSubType() )
310 case REF_BOOKMARK:
312 // #i83479#
313 SwGetRefField* pRefField = dynamic_cast<SwGetRefField*>(GetCurField());
314 if ( pRefField &&
315 pRefField->IsRefToHeadingCrossRefBookmark() )
317 sName = m_sHeadingText;
318 nFlag = REFFLDFLAG_HEADING;
320 else if ( pRefField &&
321 pRefField->IsRefToNumItemCrossRefBookmark() )
323 sName = m_sNumItemText;
324 nFlag = REFFLDFLAG_NUMITEM;
326 else
328 sName = m_sBookmarkText;
329 nFlag = REFFLDFLAG_BOOKMARK;
332 break;
334 case REF_FOOTNOTE:
335 sName = m_sFootnoteText;
336 nFlag = REFFLDFLAG_FOOTNOTE;
337 break;
339 case REF_ENDNOTE:
340 sName = m_sEndnoteText;
341 nFlag = REFFLDFLAG_ENDNOTE;
342 break;
344 case REF_SETREFATTR:
345 sName = SwResId(STR_GETREFFLD);
346 nFlag = REF_SETREFATTR;
347 break;
349 case REF_SEQUENCEFLD:
351 SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField()));
352 if (pRefField)
354 sName = pRefField->GetSetRefName();
356 nFlag = REFFLDFLAG;
357 break;
361 if (m_xTypeLB->find_text(sName) == -1) // reference to deleted mark
363 m_xTypeLB->append(OUString::number(nFlag), sName);
366 m_xTypeLB->select_text(sName);
367 SetTypeSel(m_xTypeLB->get_selected_index());
369 else
371 SetTypeSel(0);
372 m_xTypeLB->select(0);
376 if (nOld == GetTypeSel())
377 return;
379 sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
381 bool bName = false;
382 nFieldDlgFormatSel = 0;
384 if ( ( !IsFieldEdit() || m_xSelectionLB->n_children() ) &&
385 nOld != -1 )
387 m_xNameED->set_text(OUString());
388 m_xValueED->set_text(OUString());
389 m_xFilterED->set_text(OUString());
392 // fill selection-ListBox
393 UpdateSubType(comphelper::string::strip(m_xFilterED->get_text(), ' '));
395 switch (nTypeId)
397 case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef):
398 if (nOld != -1 && REFFLDFLAG & m_xTypeLB->get_id(nOld).toUInt32())
399 // the old one stays
400 nFieldDlgFormatSel = m_xFormatLB->get_selected_index();
401 bName = true;
402 break;
404 case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef):
405 bName = true;
406 break;
408 case REFFLDFLAG_BOOKMARK:
409 bName = true;
410 [[fallthrough]];
411 default:
412 if( REFFLDFLAG & nTypeId )
414 const sal_uInt16 nOldId = nOld != -1 ? m_xTypeLB->get_id(nOld).toUInt32() : 0;
415 if( nOldId & REFFLDFLAG || nOldId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef) )
416 // then the old one stays
417 nFieldDlgFormatSel = m_xFormatLB->get_selected_index();
419 break;
422 m_xNameED->set_sensitive(bName);
423 m_xNameFT->set_sensitive(bName);
425 // fill Format-Listbox
426 sal_Int32 nSize = FillFormatLB(nTypeId);
427 bool bFormat = nSize != 0;
428 m_xFormat->set_sensitive(bFormat);
430 SubTypeHdl();
431 ModifyHdl(*m_xNameED);
432 ModifyHdl(*m_xFilterED);
435 IMPL_LINK_NOARG(SwFieldRefPage, SubTypeTreeListBoxHdl, weld::TreeView&, void)
437 SubTypeHdl();
440 IMPL_LINK_NOARG(SwFieldRefPage, SubTypeListBoxHdl, weld::TreeView&, void)
442 SubTypeHdl();
445 void SwFieldRefPage::SubTypeHdl()
447 sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
449 switch(nTypeId)
451 case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef):
452 if (!IsFieldEdit() || m_xSelectionLB->get_selected_index() != -1)
454 m_xNameED->set_text(m_xSelectionLB->get_selected_text());
455 ModifyHdl(*m_xNameED);
457 break;
459 case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef):
461 SwWrtShell *pSh = GetWrtShell();
462 if(!pSh)
463 pSh = ::GetActiveWrtShell();
464 if(pSh)
466 m_xValueED->set_text(pSh->GetSelText());
470 break;
471 // #i83479#
472 case REFFLDFLAG_HEADING:
473 case REFFLDFLAG_NUMITEM:
475 int nEntry = m_xSelectionToolTipLB->get_selected_index();
476 if (nEntry != -1)
477 m_xNameED->set_text(m_xSelectionToolTipLB->get_text(nEntry));
479 break;
481 default:
482 if (!IsFieldEdit() || m_xSelectionLB->get_selected_index() != -1)
483 m_xNameED->set_text(m_xSelectionLB->get_selected_text());
484 break;
488 // renew types in SelectionLB after filtering
489 void SwFieldRefPage::UpdateSubType(const OUString& filterString)
491 SwWrtShell *pSh = GetWrtShell();
492 if (!pSh)
493 pSh = ::GetActiveWrtShell();
494 if (!pSh)
495 return;
497 SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField()));
498 const sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
500 OUString sOldSel;
501 // #i83479#
502 if ( m_xSelectionLB->get_visible() )
504 const sal_Int32 nSelectionSel = m_xSelectionLB->get_selected_index();
505 if (nSelectionSel != -1)
506 sOldSel = m_xSelectionLB->get_text(nSelectionSel);
508 if (IsFieldEdit() && pRefField && sOldSel.isEmpty())
509 sOldSel = OUString::number( pRefField->GetSeqNo() + 1 );
511 m_xSelectionLB->freeze();
512 m_xSelectionLB->clear();
514 if (REFFLDFLAG & nTypeId)
516 if (nTypeId == REFFLDFLAG_FOOTNOTE || nTypeId == REFFLDFLAG_ENDNOTE)
518 m_xSelectionLB->thaw();
519 m_xSelectionLB->make_unsorted();
520 m_xSelectionLB->freeze();
522 // #i83479#
523 else if (nTypeId != REFFLDFLAG_HEADING && nTypeId != REFFLDFLAG_NUMITEM)
525 m_xSelectionLB->thaw();
526 m_xSelectionLB->make_sorted();
527 m_xSelectionLB->freeze();
531 // #i83479#
532 m_xSelectionToolTipLB->freeze();
533 m_xSelectionToolTipLB->clear();
534 OUString m_sSelectionToolTipLBId;
535 bool bShowSelectionToolTipLB( false );
537 if( REFFLDFLAG & nTypeId )
539 if (nTypeId == REFFLDFLAG_BOOKMARK) // text marks!
541 // get all text marks
542 IDocumentMarkAccess* const pMarkAccess = pSh->getIDocumentMarkAccess();
543 for(IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getBookmarksBegin();
544 ppMark != pMarkAccess->getBookmarksEnd();
545 ++ppMark)
547 const ::sw::mark::IMark* pBkmk = *ppMark;
548 if(IDocumentMarkAccess::MarkType::BOOKMARK == IDocumentMarkAccess::GetType(*pBkmk))
550 bool isSubstring = MatchSubstring(pBkmk->GetName(), filterString);
551 if(isSubstring)
553 m_xSelectionLB->append_text( pBkmk->GetName() );
557 if (IsFieldEdit() && pRefField)
558 sOldSel = pRefField->GetSetRefName();
560 else if (nTypeId == REFFLDFLAG_FOOTNOTE)
562 SwSeqFieldList aArr;
563 const size_t nCnt = pSh->GetSeqFootnoteList( aArr );
565 for( size_t n = 0; n < nCnt; ++n )
567 bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString);
568 if(isSubstring)
570 m_xSelectionLB->append_text( aArr[ n ].sDlgEntry );
572 if (IsFieldEdit() && pRefField && pRefField->GetSeqNo() == aArr[ n ].nSeqNo)
573 sOldSel = aArr[n].sDlgEntry;
576 else if (nTypeId == REFFLDFLAG_ENDNOTE)
578 SwSeqFieldList aArr;
579 const size_t nCnt = pSh->GetSeqFootnoteList( aArr, true );
581 for( size_t n = 0; n < nCnt; ++n )
583 bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString);
584 if(isSubstring)
586 m_xSelectionLB->append_text( aArr[ n ].sDlgEntry );
588 if (IsFieldEdit() && pRefField && pRefField->GetSeqNo() == aArr[ n ].nSeqNo)
589 sOldSel = aArr[n].sDlgEntry;
592 // #i83479#
593 else if ( nTypeId == REFFLDFLAG_HEADING )
595 bShowSelectionToolTipLB = true;
597 const IDocumentOutlineNodes* pIDoc( pSh->getIDocumentOutlineNodesAccess() );
598 pIDoc->getOutlineNodes( maOutlineNodes );
599 bool bCertainTextNodeSelected( false );
600 for ( size_t nOutlIdx = 0; nOutlIdx < maOutlineNodes.size(); ++nOutlIdx )
602 if (!pIDoc->isOutlineInLayout(nOutlIdx, *pSh->GetLayout()))
604 continue; // skip it
606 bool isSubstring = MatchSubstring(pIDoc->getOutlineText(nOutlIdx, pSh->GetLayout(), true, true, false), filterString);
607 if(isSubstring)
609 OUString sId(OUString::number(nOutlIdx));
610 m_xSelectionToolTipLB->append(sId,
611 pIDoc->getOutlineText(nOutlIdx, pSh->GetLayout(), true, true, false));
612 if ((IsFieldEdit() && pRefField
613 && pRefField->GetReferencedTextNode() == maOutlineNodes[nOutlIdx])
614 || mpSavedSelectedTextNode == maOutlineNodes[nOutlIdx])
616 m_sSelectionToolTipLBId = sId;
617 sOldSel.clear();
618 bCertainTextNodeSelected = true;
620 else if ( !bCertainTextNodeSelected && mnSavedSelectedPos == nOutlIdx )
622 m_sSelectionToolTipLBId = sId;
623 sOldSel.clear();
628 else if ( nTypeId == REFFLDFLAG_NUMITEM )
630 bShowSelectionToolTipLB = true;
632 const IDocumentListItems* pIDoc( pSh->getIDocumentListItemsAccess() );
633 pIDoc->getNumItems( maNumItems );
634 bool bCertainTextNodeSelected( false );
635 for ( size_t nNumItemIdx = 0; nNumItemIdx < maNumItems.size(); ++nNumItemIdx )
637 if (!pIDoc->isNumberedInLayout(*maNumItems[nNumItemIdx], *pSh->GetLayout()))
639 continue; // skip it
641 bool isSubstring = MatchSubstring(pIDoc->getListItemText(*maNumItems[nNumItemIdx], *pSh->GetLayout()), filterString);
642 if(isSubstring)
644 OUString sId(OUString::number(nNumItemIdx));
645 m_xSelectionToolTipLB->append(sId,
646 pIDoc->getListItemText(*maNumItems[nNumItemIdx], *pSh->GetLayout()));
647 if ((IsFieldEdit() && pRefField
648 && pRefField->GetReferencedTextNode() == maNumItems[nNumItemIdx]->GetTextNode())
649 || mpSavedSelectedTextNode == maNumItems[nNumItemIdx]->GetTextNode())
651 m_sSelectionToolTipLBId = sId;
652 sOldSel.clear();
653 bCertainTextNodeSelected = true;
655 else if ( !bCertainTextNodeSelected && mnSavedSelectedPos == nNumItemIdx )
657 m_sSelectionToolTipLBId = sId;
658 sOldSel.clear();
663 else
665 // get the fields to Seq-FieldType:
667 SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType(
668 nTypeId & ~REFFLDFLAG, SwFieldIds::SetExp ));
669 if( pType )
671 SwSeqFieldList aArr;
672 // old selection should be kept in non-edit mode
673 if(IsFieldEdit())
674 sOldSel.clear();
676 const size_t nCnt = pType->GetSeqFieldList(aArr, pSh->GetLayout());
677 for( size_t n = 0; n < nCnt; ++n )
679 bool isSubstring = MatchSubstring(aArr[ n ].sDlgEntry, filterString);
680 if(isSubstring)
682 m_xSelectionLB->append_text( aArr[ n ].sDlgEntry );
684 if (IsFieldEdit() && pRefField && sOldSel.isEmpty() &&
685 aArr[ n ].nSeqNo == pRefField->GetSeqNo())
686 sOldSel = aArr[ n ].sDlgEntry;
689 if (IsFieldEdit() && pRefField && sOldSel.isEmpty())
690 sOldSel = OUString::number( pRefField->GetSeqNo() + 1);
694 else
696 std::vector<OUString> aLst;
697 GetFieldMgr().GetSubTypes(static_cast<SwFieldTypesEnum>(nTypeId), aLst);
698 for(const OUString & i : aLst)
700 bool isSubstring = MatchSubstring( i , filterString );
701 if(isSubstring)
703 m_xSelectionLB->append_text(i);
707 if (IsFieldEdit() && pRefField)
708 sOldSel = pRefField->GetSetRefName();
711 // #i83479#
712 m_xSelectionLB->thaw();
713 m_xSelectionToolTipLB->thaw();
714 if (!m_sSelectionToolTipLBId.isEmpty())
715 m_xSelectionToolTipLB->select_id(m_sSelectionToolTipLBId);
716 m_xSelectionToolTipLB->set_visible( bShowSelectionToolTipLB );
717 m_xSelectionLB->set_visible( !bShowSelectionToolTipLB );
718 if ( bShowSelectionToolTipLB )
720 bool bEnable = m_xSelectionToolTipLB->n_children() != 0;
721 m_xSelection->set_sensitive( bEnable );
723 int nEntry = m_xSelectionToolTipLB->get_selected_index();
724 if (nEntry != -1)
725 m_xSelectionToolTipLB->scroll_to_row(nEntry);
727 if (IsFieldEdit() && nEntry == -1)
729 m_xNameED->set_text(sOldSel);
732 else
734 // enable or disable
735 bool bEnable = m_xSelectionLB->n_children() != 0;
736 m_xSelection->set_sensitive( bEnable );
738 if ( bEnable )
740 m_xSelectionLB->select_text(sOldSel);
741 if (m_xSelectionLB->get_selected_index() == -1 && !IsFieldEdit())
742 m_xSelectionLB->select(0);
745 if (IsFieldEdit() && m_xSelectionLB->get_selected_index() == -1) // in case the reference was already deleted...
746 m_xNameED->set_text(sOldSel);
750 bool SwFieldRefPage::MatchSubstring( const OUString& rListString, const OUString& rSubstr )
752 if(rSubstr.isEmpty())
753 return true;
754 OUString aListString = GetAppCharClass().lowercase(rListString);
755 OUString aSubstr = GetAppCharClass().lowercase(rSubstr);
756 return aListString.indexOf(aSubstr) >= 0;
759 namespace {
761 enum FMT_REF_IDX
763 FMT_REF_PAGE_IDX = 0,
764 FMT_REF_CHAPTER_IDX = 1,
765 FMT_REF_TEXT_IDX = 2,
766 FMT_REF_UPDOWN_IDX = 3,
767 FMT_REF_PAGE_PGDSC_IDX = 4,
768 FMT_REF_ONLYNUMBER_IDX = 5,
769 FMT_REF_ONLYCAPTION_IDX = 6,
770 FMT_REF_ONLYSEQNO_IDX = 7,
771 FMT_REF_NUMBER_IDX = 8,
772 FMT_REF_NUMBER_NO_CONTEXT_IDX = 9,
773 FMT_REF_NUMBER_FULL_CONTEXT_IDX = 10
778 const TranslateId FMT_REF_ARY[] =
780 FMT_REF_PAGE,
781 FMT_REF_CHAPTER,
782 FMT_REF_TEXT,
783 FMT_REF_UPDOWN,
784 FMT_REF_PAGE_PGDSC,
785 FMT_REF_ONLYNUMBER,
786 FMT_REF_ONLYCAPTION,
787 FMT_REF_ONLYSEQNO,
788 FMT_REF_NUMBER,
789 FMT_REF_NUMBER_NO_CONTEXT,
790 FMT_REF_NUMBER_FULL_CONTEXT
793 sal_Int32 SwFieldRefPage::FillFormatLB(sal_uInt16 nTypeId)
795 OUString sOldSel;
797 sal_Int32 nFormatSel = m_xFormatLB->get_selected_index();
798 if (nFormatSel != -1)
799 sOldSel = m_xFormatLB->get_text(nFormatSel);
801 // fill Format-Listbox
802 m_xFormatLB->clear();
804 // reference has less that the annotation
805 sal_uInt16 nSize( 0 );
806 bool bAddCrossRefFormats( false );
807 switch (nTypeId)
809 // #i83479#
810 case REFFLDFLAG_HEADING:
811 case REFFLDFLAG_NUMITEM:
812 bAddCrossRefFormats = true;
813 [[fallthrough]];
815 case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef):
816 case REFFLDFLAG_BOOKMARK:
817 case REFFLDFLAG_FOOTNOTE:
818 case REFFLDFLAG_ENDNOTE:
819 nSize = FMT_REF_PAGE_PGDSC_IDX + 1;
820 break;
822 default:
823 // #i83479#
825 if ( REFFLDFLAG & nTypeId )
827 nSize = FMT_REF_ONLYSEQNO_IDX + 1;
829 else
831 nSize = GetFieldMgr().GetFormatCount( static_cast<SwFieldTypesEnum>(nTypeId), IsFieldDlgHtmlMode() );
833 break;
836 if (REFFLDFLAG & nTypeId)
837 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
839 SwFieldTypesEnum nFieldType = static_cast<SwFieldTypesEnum>(nTypeId);
840 for (sal_uInt16 i = 0; i < nSize; i++)
842 OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i )));
843 m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(nFieldType, i));
845 // #i83479#
847 sal_uInt16 nExtraSize( 0 );
848 if ( bAddCrossRefFormats )
850 sal_uInt16 nFormat = FMT_REF_NUMBER_IDX;
851 OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)));
852 m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat ));
853 nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX;
854 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
855 m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat ));
856 nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX;
857 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
858 m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr( nFieldType, nFormat ));
859 nExtraSize = 3;
862 // extra list items optionally, depending from reference-language
863 SvtSysLocaleOptions aSysLocaleOptions;
864 static const LanguageTag& rLang = aSysLocaleOptions.GetRealLanguageTag();
866 if (rLang.getLanguage() == "hu")
868 for (sal_uInt16 i = 0; i < nSize; i++)
870 OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i + SAL_N_ELEMENTS(FMT_REF_ARY))));
871 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, i ));
873 nExtraSize += nSize;
875 if ( bAddCrossRefFormats )
877 sal_uInt16 nFormat = FMT_REF_NUMBER_IDX + SAL_N_ELEMENTS(FMT_REF_ARY);
878 OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)));
879 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
880 nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX + SAL_N_ELEMENTS(FMT_REF_ARY);
881 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
882 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
883 nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX + SAL_N_ELEMENTS(FMT_REF_ARY);
884 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
885 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_LOWERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
886 nExtraSize += 3;
888 // uppercase article
889 for (sal_uInt16 i = 0; i < nSize; i++)
891 OUString sId(OUString::number(GetFieldMgr().GetFormatId( nFieldType, i + 2 * SAL_N_ELEMENTS(FMT_REF_ARY))));
892 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, i ));
894 nExtraSize += nSize;
895 if ( bAddCrossRefFormats )
897 sal_uInt16 nFormat = FMT_REF_NUMBER_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY);
898 OUString sId(OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat)));
899 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
900 nFormat = FMT_REF_NUMBER_NO_CONTEXT_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY);
901 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
902 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
903 nFormat = FMT_REF_NUMBER_FULL_CONTEXT_IDX + 2 * SAL_N_ELEMENTS(FMT_REF_ARY);
904 sId = OUString::number(GetFieldMgr().GetFormatId(nFieldType, nFormat));
905 m_xFormatLB->append(sId, SwResId(FMT_REF_WITH_UPPERCASE_HU_ARTICLE) + GetFieldMgr().GetFormatStr( nFieldType, nFormat % SAL_N_ELEMENTS(FMT_REF_ARY)));
906 nExtraSize += 3;
910 nSize += nExtraSize;
912 // select a certain entry
913 if (nSize)
915 if (!IsFieldEdit())
916 m_xFormatLB->select_text(sOldSel);
917 else
918 m_xFormatLB->select_text(SwResId(FMT_REF_ARY[GetCurField()->GetFormat() % SAL_N_ELEMENTS(FMT_REF_ARY)]));
920 if (m_xFormatLB->get_selected_index() == -1)
922 if (nFieldDlgFormatSel < m_xFormatLB->n_children())
923 m_xFormatLB->select(nFieldDlgFormatSel);
924 else
925 m_xFormatLB->select(0);
929 return nSize;
932 // Modify
933 IMPL_LINK_NOARG(SwFieldRefPage, ModifyHdl, weld::Entry&, void)
935 OUString aName(m_xNameED->get_text());
936 const bool bEmptyName = aName.isEmpty();
938 bool bEnable = true;
939 sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
941 if ((nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef) && !GetFieldMgr().CanInsertRefMark(aName)) ||
942 (bEmptyName && (nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef) || nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef) ||
943 nTypeId == REFFLDFLAG_BOOKMARK)))
944 bEnable = false;
946 EnableInsert(bEnable);
948 m_xSelectionLB->select_text(aName);
951 bool SwFieldRefPage::FillItemSet(SfxItemSet* )
953 bool bModified = false;
954 sal_uInt16 nTypeId = m_xTypeLB->get_id(GetTypeSel()).toUInt32();
956 sal_uInt16 nSubType = 0;
957 const sal_Int32 nEntryPos = m_xFormatLB->get_selected_index();
958 const sal_uInt32 nFormat = (nEntryPos == -1)
959 ? 0 : m_xFormatLB->get_id(nEntryPos).toUInt32();
961 OUString aVal(m_xValueED->get_text());
962 OUString aName(m_xNameED->get_text());
964 switch(nTypeId)
966 case static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef):
967 nSubType = REF_SETREFATTR;
968 break;
970 case static_cast<sal_uInt16>(SwFieldTypesEnum::SetRef):
972 SwFieldType* pType = GetFieldMgr().GetFieldType(SwFieldIds::SetExp, aName);
974 if(!pType) // Only insert when the name doesn't exist yet
976 m_xSelectionLB->append_text(aName);
977 m_xSelection->set_sensitive(true);
979 break;
983 SwGetRefField const*const pRefField(dynamic_cast<SwGetRefField*>(GetCurField()));
985 SwWrtShell *pSh = GetWrtShell();
986 if(!pSh)
987 pSh = ::GetActiveWrtShell();
989 if (pSh && REFFLDFLAG & nTypeId)
991 if (nTypeId == REFFLDFLAG_BOOKMARK) // text marks!
993 aName = m_xNameED->get_text();
994 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
995 nSubType = REF_BOOKMARK;
997 else if (REFFLDFLAG_FOOTNOTE == nTypeId) // footnotes
999 SwSeqFieldList aArr;
1000 SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 );
1002 size_t nPos = 0;
1004 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
1005 nSubType = REF_FOOTNOTE;
1006 aName.clear();
1008 if (pSh->GetSeqFootnoteList(aArr) && aArr.SeekEntry(aElem, &nPos))
1010 aVal = OUString::number( aArr[nPos].nSeqNo );
1012 if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo())
1013 bModified = true; // can happen with fields of which the references were deleted
1015 else if (IsFieldEdit() && pRefField)
1016 aVal = OUString::number( pRefField->GetSeqNo() );
1018 else if (REFFLDFLAG_ENDNOTE == nTypeId) // endnotes
1020 SwSeqFieldList aArr;
1021 SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 );
1023 size_t nPos = 0;
1025 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
1026 nSubType = REF_ENDNOTE;
1027 aName.clear();
1029 if (pSh->GetSeqFootnoteList(aArr, true) && aArr.SeekEntry(aElem, &nPos))
1031 aVal = OUString::number( aArr[nPos].nSeqNo );
1033 if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo())
1034 bModified = true; // can happen with fields of which the reference was deleted
1036 else if (IsFieldEdit() && pRefField)
1037 aVal = OUString::number( pRefField->GetSeqNo() );
1039 // #i83479#
1040 else if ( nTypeId == REFFLDFLAG_HEADING )
1042 int nEntry = m_xSelectionToolTipLB->get_selected_index();
1043 OSL_ENSURE( nEntry != -1,
1044 "<SwFieldRefPage::FillItemSet(..)> - no entry selected in selection tool tip listbox!" );
1045 if (nEntry != -1)
1047 const size_t nOutlIdx(m_xSelectionToolTipLB->get_id(nEntry).toUInt32());
1048 pSh->getIDocumentOutlineNodesAccess()->getOutlineNodes( maOutlineNodes );
1049 if ( nOutlIdx < maOutlineNodes.size() )
1051 ::sw::mark::IMark const * const pMark = pSh->getIDocumentMarkAccess()->getMarkForTextNode(
1052 *(maOutlineNodes[nOutlIdx]),
1053 IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK);
1054 aName = pMark->GetName();
1055 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
1056 nSubType = REF_BOOKMARK;
1060 else if ( nTypeId == REFFLDFLAG_NUMITEM )
1062 int nEntry = m_xSelectionToolTipLB->get_selected_index();
1063 OSL_ENSURE( nEntry != -1,
1064 "<SwFieldRefPage::FillItemSet(..)> - no entry selected in selection tool tip listbox!" );
1065 if (nEntry != -1)
1067 const size_t nNumItemIdx(m_xSelectionToolTipLB->get_id(nEntry).toUInt32());
1068 pSh->getIDocumentListItemsAccess()->getNumItems(maNumItems);
1069 if ( nNumItemIdx < maNumItems.size() )
1071 ::sw::mark::IMark const * const pMark = pSh->getIDocumentMarkAccess()->getMarkForTextNode(
1072 *(maNumItems[nNumItemIdx]->GetTextNode()),
1073 IDocumentMarkAccess::MarkType::CROSSREF_NUMITEM_BOOKMARK);
1074 aName = pMark->GetName();
1075 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
1076 nSubType = REF_BOOKMARK;
1080 else // SequenceFields
1082 // get fields for Seq-FieldType:
1083 SwSetExpFieldType* pType = static_cast<SwSetExpFieldType*>(pSh->GetFieldType(
1084 nTypeId & ~REFFLDFLAG, SwFieldIds::SetExp ));
1085 if( pType )
1087 SwSeqFieldList aArr;
1088 SeqFieldLstElem aElem( m_xSelectionLB->get_selected_text(), 0 );
1090 size_t nPos = 0;
1092 nTypeId = static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef);
1093 nSubType = REF_SEQUENCEFLD;
1094 aName = pType->GetName();
1096 if (pType->GetSeqFieldList(aArr, pSh->GetLayout())
1097 && aArr.SeekEntry(aElem, &nPos))
1099 aVal = OUString::number( aArr[nPos].nSeqNo );
1101 if (IsFieldEdit() && pRefField && aArr[nPos].nSeqNo == pRefField->GetSeqNo())
1102 bModified = true; // can happen with fields of which the reference was deleted
1104 else if (IsFieldEdit() && pRefField)
1105 aVal = OUString::number( pRefField->GetSeqNo() );
1110 if (IsFieldEdit() && nTypeId == static_cast<sal_uInt16>(SwFieldTypesEnum::GetRef))
1112 aVal = OUString::number(nSubType) + "|" + aVal;
1115 if (!IsFieldEdit() || bModified ||
1116 m_xNameED->get_value_changed_from_saved() ||
1117 m_xValueED->get_value_changed_from_saved() ||
1118 m_xTypeLB->get_value_changed_from_saved() ||
1119 m_xSelectionLB->get_value_changed_from_saved() ||
1120 m_xFormatLB->get_value_changed_from_saved())
1122 InsertField( static_cast<SwFieldTypesEnum>(nTypeId), nSubType, aName, aVal, nFormat );
1125 ModifyHdl(*m_xNameED); // enable/disable insert if applicable
1127 return false;
1130 std::unique_ptr<SfxTabPage> SwFieldRefPage::Create( weld::Container* pPage, weld::DialogController* pController,
1131 const SfxItemSet *const pAttrSet)
1133 return std::make_unique<SwFieldRefPage>(pPage, pController, pAttrSet);
1136 sal_uInt16 SwFieldRefPage::GetGroup()
1138 return GRP_REF;
1141 void SwFieldRefPage::FillUserData()
1143 const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index();
1144 const sal_uInt16 nTypeSel = ( -1 == nEntryPos )
1145 ? USHRT_MAX
1146 : m_xTypeLB->get_id(nEntryPos).toUInt32();
1147 const sal_Int32 nFormatEntryPos = m_xFormatLB->get_selected_index();
1148 const sal_uInt32 nFormatSel = -1 == nFormatEntryPos ? USHRT_MAX : nFormatEntryPos;
1149 SetUserData( USER_DATA_VERSION ";" +
1150 OUString::number( nTypeSel ) + ";" +
1151 OUString::number( nFormatSel ));
1154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */