sw/inc/IDocumentMarkAccess.hxx      |    4 ++--
 sw/inc/crsrsh.hxx                   |    4 ++--
 sw/qa/extras/uiwriter/uiwriter4.cxx |    2 +-
 sw/source/core/crsr/crbm.cxx        |    8 ++++----
 sw/source/core/doc/docbm.cxx        |   27 ++++++++++++++++++++-------
 sw/source/core/inc/MarkManager.hxx  |    4 ++--
 sw/source/ui/vba/vbaformfield.cxx   |   10 ++++++----
 sw/source/uibase/docvw/edtwin.cxx   |    6 ++++--
 sw/source/uibase/wrtsh/wrtsh1.cxx   |    4 ++--
 9 files changed, 43 insertions(+), 26 deletions(-)

New commits:
commit 28b55ce5943712ffa17f5e9a35d5945765fc71fe
Author:     Justin Luth <justin.l...@collabora.com>
AuthorDate: Mon Jan 23 11:18:44 2023 -0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Feb 7 07:19:49 2023 +0000

    related tdf#151548 formfield navigation: loop to beginning/end
    
    When reaching the end of the form using keyboard navigation,
    the next tabstop should return the user to the beginning of
    the form.
    
    This patch adds that to the existing legacy formfield navigation.
    I'll wait with a unit test until I have added
    activeX/contentControls into the mix.
    
    Change-Id: I24a15a60f5a0a2721f512cca50397efddcbf7e4b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146035
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146562
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/inc/IDocumentMarkAccess.hxx b/sw/inc/IDocumentMarkAccess.hxx
index 9ff1a311768a..03c3dcfce648 100644
--- a/sw/inc/IDocumentMarkAccess.hxx
+++ b/sw/inc/IDocumentMarkAccess.hxx
@@ -329,8 +329,8 @@ class IDocumentMarkAccess
         /// get Fieldmark for CH_TXT_ATR_FIELDSTART/CH_TXT_ATR_FIELDEND at rPos
         virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& rPos) 
const =0;
         virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& pos) 
const =0;
-        virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& 
pos) const =0;
-        virtual ::sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& 
pos) const =0;
+        virtual sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& 
pos, bool bLoop) const =0;
+        virtual sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& pos, 
bool bLoop) const =0;
 
         virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition& pos) 
const=0;
         virtual std::vector<::sw::mark::IFieldmark*> 
getNoTextFieldmarksIn(const SwPaM &rPaM) const=0;
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 9f79a515153a..25e95c415fa4 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -571,8 +571,8 @@ public:
 
     bool IsFormProtected();
     ::sw::mark::IFieldmark* GetCurrentFieldmark();
-    ::sw::mark::IFieldmark* GetFieldmarkAfter();
-    ::sw::mark::IFieldmark* GetFieldmarkBefore();
+    sw::mark::IFieldmark* GetFieldmarkAfter(bool bLoop);
+    sw::mark::IFieldmark* GetFieldmarkBefore(bool bLoop);
     bool GotoFieldmark( const ::sw::mark::IFieldmark* const pMark );
 
     // update Cursr, i.e. reset it into content should only be called when the
diff --git a/sw/qa/extras/uiwriter/uiwriter4.cxx 
b/sw/qa/extras/uiwriter/uiwriter4.cxx
index 76f0506d52fa..967ed5007522 100644
--- a/sw/qa/extras/uiwriter/uiwriter4.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter4.cxx
@@ -1447,7 +1447,7 @@ void SwUiWriterTest4::testTdf95699()
     pMarkAccess = aClipboard.getIDocumentMarkAccess();
     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pMarkAccess->getAllMarksCount());
     ::sw::mark::IFieldmark* pFieldMark
-        = 
pMarkAccess->getFieldmarkAfter(SwPosition(pDoc->GetNodes().GetEndOfExtras()));
+        = 
pMarkAccess->getFieldmarkAfter(SwPosition(pDoc->GetNodes().GetEndOfExtras()), 
false);
     CPPUNIT_ASSERT_EQUAL(OUString("vnd.oasis.opendocument.field.FORMCHECKBOX"),
                          pFieldMark->GetFieldname());
 }
diff --git a/sw/source/core/crsr/crbm.cxx b/sw/source/core/crsr/crbm.cxx
index bb17940a01d6..d171b1d52be1 100644
--- a/sw/source/core/crsr/crbm.cxx
+++ b/sw/source/core/crsr/crbm.cxx
@@ -290,16 +290,16 @@ bool SwCursorShell::IsFormProtected()
     return getIDocumentMarkAccess()->getFieldmarkFor(pos);
 }
 
-::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter()
+sw::mark::IFieldmark* SwCursorShell::GetFieldmarkAfter(bool bLoop)
 {
     SwPosition pos(*GetCursor()->GetPoint());
-    return getIDocumentMarkAccess()->getFieldmarkAfter(pos);
+    return getIDocumentMarkAccess()->getFieldmarkAfter(pos, bLoop);
 }
 
-::sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore()
+sw::mark::IFieldmark* SwCursorShell::GetFieldmarkBefore(bool bLoop)
 {
     SwPosition pos(*GetCursor()->GetPoint());
-    return getIDocumentMarkAccess()->getFieldmarkBefore(pos);
+    return getIDocumentMarkAccess()->getFieldmarkBefore(pos, bLoop);
 }
 
 bool SwCursorShell::GotoFieldmark(::sw::mark::IFieldmark const * const pMark)
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index fcce59889b48..19e229f45684 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -314,7 +314,8 @@ namespace
     };
 
 
-    IMark* lcl_getMarkAfter(const MarkManager::container_t& rMarks, const 
SwPosition& rPos)
+    IMark* lcl_getMarkAfter(const MarkManager::container_t& rMarks, const 
SwPosition& rPos,
+                            bool bLoop)
     {
         auto const pMarkAfter = upper_bound(
             rMarks.begin(),
@@ -322,11 +323,17 @@ namespace
             rPos,
             CompareIMarkStartsAfter());
         if(pMarkAfter == rMarks.end())
+        {
+            if (bLoop && rMarks.begin() != rMarks.end())
+                return *rMarks.begin();
+
             return nullptr;
+        }
         return *pMarkAfter;
     };
 
-    IMark* lcl_getMarkBefore(const MarkManager::container_t& rMarks, const 
SwPosition& rPos)
+    IMark* lcl_getMarkBefore(const MarkManager::container_t& rMarks, const 
SwPosition& rPos,
+                             bool bLoop)
     {
         // candidates from which to choose the mark before
         MarkManager::container_t vCandidates;
@@ -344,7 +351,13 @@ namespace
             back_inserter(vCandidates),
             [&rPos] (const ::sw::mark::MarkBase *const pMark) { return 
!(pMark->GetMarkEnd() < rPos); } );
         // no candidate left => we are in front of the first mark or there are 
none
-        if(vCandidates.empty()) return nullptr;
+        if(vCandidates.empty())
+        {
+            if (bLoop && rMarks.begin() != rMarks.end())
+                return *(rMarks.end() - 1);
+
+            return nullptr;
+        }
         // return the highest (last) candidate using mark end ordering
         return *max_element(vCandidates.begin(), vCandidates.end(), 
&lcl_MarkOrderingByEnd);
     }
@@ -1620,11 +1633,11 @@ namespace sw::mark
         return aRet;
     }
 
-    IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos) const
-        { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, 
rPos)); }
+    IFieldmark* MarkManager::getFieldmarkAfter(const SwPosition& rPos, bool 
bLoop) const
+        { return dynamic_cast<IFieldmark*>(lcl_getMarkAfter(m_vFieldmarks, 
rPos, bLoop)); }
 
-    IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos) const
-        { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, 
rPos)); }
+    IFieldmark* MarkManager::getFieldmarkBefore(const SwPosition& rPos, bool 
bLoop) const
+        { return dynamic_cast<IFieldmark*>(lcl_getMarkBefore(m_vFieldmarks, 
rPos, bLoop)); }
 
     IDocumentMarkAccess::const_iterator_t 
MarkManager::getAnnotationMarksBegin() const
     {
diff --git a/sw/source/core/inc/MarkManager.hxx 
b/sw/source/core/inc/MarkManager.hxx
index 6c84d1a4c4b3..214bcae02669 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -91,8 +91,8 @@ namespace sw::mark {
             virtual const_iterator_t getFieldmarksEnd() const override;
             virtual ::sw::mark::IFieldmark* getFieldmarkAt(const SwPosition& 
rPos) const override;
             virtual ::sw::mark::IFieldmark* getFieldmarkFor(const SwPosition& 
rPos) const override;
-            virtual ::sw::mark::IFieldmark* getFieldmarkBefore(const 
SwPosition& rPos) const override;
-            virtual ::sw::mark::IFieldmark* getFieldmarkAfter(const 
SwPosition& rPos) const override;
+            virtual sw::mark::IFieldmark* getFieldmarkBefore(const SwPosition& 
rPos, bool bLoop) const override;
+            virtual sw::mark::IFieldmark* getFieldmarkAfter(const SwPosition& 
rPos, bool bLoop) const override;
 
             virtual ::sw::mark::IFieldmark* getDropDownFor(const SwPosition 
&rPos) const override;
             virtual std::vector<::sw::mark::IFieldmark*> 
getNoTextFieldmarksIn(const SwPaM &rPaM) const override;
diff --git a/sw/source/ui/vba/vbaformfield.cxx 
b/sw/source/ui/vba/vbaformfield.cxx
index 0c8a8644e990..cde8d5e5c337 100644
--- a/sw/source/ui/vba/vbaformfield.cxx
+++ b/sw/source/ui/vba/vbaformfield.cxx
@@ -74,13 +74,14 @@ uno::Any SAL_CALL SwVbaFormField::Previous()
     if (!pMarkAccess)
         return uno::Any();
 
-    sw::mark::IFieldmark* pFieldMark = 
pMarkAccess->getFieldmarkBefore(m_rFormField.GetMarkPos());
+    sw::mark::IFieldmark* pFieldMark = 
pMarkAccess->getFieldmarkBefore(m_rFormField.GetMarkPos(),
+                                                                       
/*bLoop=*/false);
 
     // DateFields are a LO specialty, and do not exist natively in MS 
documents. Ignore if added...
     auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
     while (pDateField)
     {
-        pFieldMark = pMarkAccess->getFieldmarkBefore(pDateField->GetMarkPos());
+        pFieldMark = pMarkAccess->getFieldmarkBefore(pDateField->GetMarkPos(), 
/*bLoop=*/false);
         pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
     }
 
@@ -101,13 +102,14 @@ uno::Any SAL_CALL SwVbaFormField::Next()
     if (!pMarkAccess)
         return uno::Any();
 
-    sw::mark::IFieldmark* pFieldMark = 
pMarkAccess->getFieldmarkAfter(m_rFormField.GetMarkPos());
+    sw::mark::IFieldmark* pFieldMark = 
pMarkAccess->getFieldmarkAfter(m_rFormField.GetMarkPos(),
+                                                                      
/*bLoop=*/false);
 
     // DateFields are a LO specialty, and do not exist natively in MS 
documents. Ignore if added...
     auto pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
     while (pDateField)
     {
-        pFieldMark = pMarkAccess->getFieldmarkAfter(pDateField->GetMarkPos());
+        pFieldMark = pMarkAccess->getFieldmarkAfter(pDateField->GetMarkPos(), 
/*bLoop=*/false);
         pDateField = dynamic_cast<sw::mark::IDateFieldmark*>(pFieldMark);
     }
 
diff --git a/sw/source/uibase/docvw/edtwin.cxx 
b/sw/source/uibase/docvw/edtwin.cxx
index b4b2014cf207..595fcb391653 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -2610,14 +2610,16 @@ KEYINPUT_CHECKTABLE_INSDEL:
 
             case SwKeyState::GotoNextFieldMark:
                 {
-                    ::sw::mark::IFieldmark const * const pFieldmark = 
rSh.GetFieldmarkAfter();
+                    const sw::mark::IFieldmark* pFieldmark
+                        = rSh.GetFieldmarkAfter(/*bLoop=*/true);
                     if(pFieldmark) rSh.GotoFieldmark(pFieldmark);
                 }
                 break;
 
             case SwKeyState::GotoPrevFieldMark:
                 {
-                    ::sw::mark::IFieldmark const * const pFieldmark = 
rSh.GetFieldmarkBefore();
+                    const sw::mark::IFieldmark* pFieldmark
+                        = rSh.GetFieldmarkBefore(/*bLoop=*/true);
                     if( pFieldmark )
                         rSh.GotoFieldmark(pFieldmark);
                 }
diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx 
b/sw/source/uibase/wrtsh/wrtsh1.cxx
index c0112556e9d9..ee6dd8b806cc 100644
--- a/sw/source/uibase/wrtsh/wrtsh1.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh1.cxx
@@ -2004,7 +2004,7 @@ SwWrtShell::SwWrtShell( SwWrtShell& rSh, vcl::Window 
*_pWin, SwView &rShell )
 
     // place the cursor on the first field...
     IFieldmark *pBM = nullptr;
-    if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
+    if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/false)) 
!=nullptr) {
         GotoFieldmark(pBM);
     }
 }
@@ -2022,7 +2022,7 @@ SwWrtShell::SwWrtShell( SwDoc& rDoc, vcl::Window *_pWin, 
SwView &rShell,
 
     // place the cursor on the first field...
     IFieldmark *pBM = nullptr;
-    if ( IsFormProtected() && ( pBM = GetFieldmarkAfter( ) ) !=nullptr ) {
+    if (IsFormProtected() && (pBM = GetFieldmarkAfter(/*bLoop=*/false)) 
!=nullptr) {
         GotoFieldmark(pBM);
     }
 }

Reply via email to