sfx2/inc/SfxRedactionHelper.hxx        |   25 +++++++-
 sfx2/inc/autoredactdialog.hxx          |    7 +-
 sfx2/source/doc/SfxRedactionHelper.cxx |  103 +++++++++++++++++++++++++++------
 sfx2/source/doc/autoredactdialog.cxx   |   89 +++++++++++++++++++++++++++-
 sfx2/uiconfig/ui/addtargetdialog.ui    |   52 +++++++++++++++-
 5 files changed, 249 insertions(+), 27 deletions(-)

New commits:
commit 6afcbdf2fbe159eac03a86dfd76f5d8df4a41fe5
Author:     Muhammet Kara <muhammet.k...@collabora.com>
AuthorDate: Sat Jun 15 12:08:35 2019 +0300
Commit:     Muhammet Kara <muhammet.k...@collabora.com>
CommitDate: Mon Jun 17 23:31:30 2019 +0200

    Add predefined targets to auto redaction
    
    Change-Id: Ib8cf8b50944667d6a87a5cafb6995ad195699358
    Reviewed-on: https://gerrit.libreoffice.org/74092
    Tested-by: Jenkins
    Reviewed-by: Muhammet Kara <muhammet.k...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74233
    Tested-by: Muhammet Kara <muhammet.k...@collabora.com>

diff --git a/sfx2/inc/SfxRedactionHelper.hxx b/sfx2/inc/SfxRedactionHelper.hxx
index 2f470386d2dc..ae72c39f4886 100644
--- a/sfx2/inc/SfxRedactionHelper.hxx
+++ b/sfx2/inc/SfxRedactionHelper.hxx
@@ -120,6 +120,20 @@ public:
     /// Fill the search options based on the given redaction target
     static void fillSearchOptions(i18nutil::SearchOptions2& rSearchOpt,
                                   const RedactionTarget* pTarget);
+
+private:
+    static constexpr OUStringLiteral m_aPredefinedTargets[6] = {
+        "\\b(?:\\d[ -]*?){13,16}\\b", //Credit card numbers
+        "\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b", //Email addresses
+        
"\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
+        
"\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
+        "\\b", //IP addresses
+        "([12]\\d{3}[./-](0[1-9]|1[0-2])[./"
+        
"-](0[1-9]|[12]\\d|3[01]))|((0[1-9]|[12]\\d|3[01])[./-](0[1-9]|1[0-2])[./"
+        "-][12]\\d{3})", //Dates (numerical)
+        "\\s*[a-zA-Z]{2}(?:\\s*\\d\\s*){6}[a-zA-Z]?\\s*", //National Insurance 
Number (UK)
+        "([1-9])(?!\\1{2}-\\1{2}-\\1{4})[1-9]{2}-[1-9]{2}-[1-9]{4}" //Social 
Security Number (US)
+    };
 };
 
 #endif // INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX
diff --git a/sfx2/inc/autoredactdialog.hxx b/sfx2/inc/autoredactdialog.hxx
index bab00cf536a3..2cec20cc64c8 100644
--- a/sfx2/inc/autoredactdialog.hxx
+++ b/sfx2/inc/autoredactdialog.hxx
@@ -155,10 +155,15 @@ class SfxAddTargetDialog : public 
weld::GenericDialogController
 private:
     std::unique_ptr<weld::Entry> m_xName;
     std::unique_ptr<weld::ComboBox> m_xType;
+    std::unique_ptr<weld::Label> m_xLabelContent;
     std::unique_ptr<weld::Entry> m_xContent;
+    std::unique_ptr<weld::Label> m_xLabelPredefContent;
+    std::unique_ptr<weld::ComboBox> m_xPredefContent;
     std::unique_ptr<weld::CheckButton> m_xCaseSensitive;
     std::unique_ptr<weld::CheckButton> m_xWholeWords;
 
+    DECL_LINK(SelectTypeHdl, weld::ComboBox&, void);
+
 public:
     SfxAddTargetDialog(weld::Window* pWindow, const OUString& rName);
     SfxAddTargetDialog(weld::Window* pWindow, const OUString& sName,
@@ -167,7 +172,7 @@ public:
 
     OUString getName() const { return m_xName->get_text(); }
     RedactionTargetType getType() const;
-    OUString getContent() const { return m_xContent->get_text(); }
+    OUString getContent() const;
     bool isCaseSensitive() const
     {
         return m_xCaseSensitive->get_state() == TriState::TRISTATE_TRUE;
diff --git a/sfx2/source/doc/SfxRedactionHelper.cxx 
b/sfx2/source/doc/SfxRedactionHelper.cxx
index 75459d093ea9..6e602b048acf 100644
--- a/sfx2/source/doc/SfxRedactionHelper.cxx
+++ b/sfx2/source/doc/SfxRedactionHelper.cxx
@@ -531,7 +531,8 @@ void 
SfxRedactionHelper::fillSearchOptions(i18nutil::SearchOptions2& rSearchOpt,
         return;
     }
 
-    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_REGEX)
+    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_REGEX
+        || pTarget->sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
     {
         rSearchOpt.algorithmType = util::SearchAlgorithms_REGEXP;
         rSearchOpt.AlgorithmType2 = util::SearchAlgorithms2::REGEXP;
@@ -543,10 +544,20 @@ void 
SfxRedactionHelper::fillSearchOptions(i18nutil::SearchOptions2& rSearchOpt,
     }
 
     rSearchOpt.Locale = GetAppLanguageTag().getLocale();
-    rSearchOpt.searchString = pTarget->sContent;
+    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
+    {
+        sal_Int32 nPredefIndex = pTarget->sContent.getToken(0, ';').toInt32();
+        //sal_Int32 nPredefIndex = sContent.toInt32();
+
+        rSearchOpt.searchString = m_aPredefinedTargets[nPredefIndex];
+    }
+    else
+        rSearchOpt.searchString = pTarget->sContent;
+
     rSearchOpt.replaceString.clear();
 
-    if (!pTarget->bCaseSensitive && pTarget->sType != 
RedactionTargetType::REDACTION_TARGET_REGEX)
+    if (!pTarget->bCaseSensitive && pTarget->sType != 
RedactionTargetType::REDACTION_TARGET_REGEX
+        && pTarget->sType != RedactionTargetType::REDACTION_TARGET_PREDEFINED)
         rSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
     if (pTarget->bWholeWords)
         rSearchOpt.searchFlag |= util::SearchFlags::NORM_WORD_ONLY;
diff --git a/sfx2/source/doc/autoredactdialog.cxx 
b/sfx2/source/doc/autoredactdialog.cxx
index 73ec02cfc420..798ab965d831 100644
--- a/sfx2/source/doc/autoredactdialog.cxx
+++ b/sfx2/source/doc/autoredactdialog.cxx
@@ -128,11 +128,19 @@ void TargetsTable::InsertTarget(RedactionTarget* pTarget)
         pTarget->sName = GetNameProposal();
     }
 
+    OUString sContent = pTarget->sContent;
+
+    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
+    {
+        //selection_num;selection_name
+        sContent = sContent.getToken(1, ';');
+    }
+
     // Add to the end
     int nRow = m_xControl->n_children();
     m_xControl->append(OUString::number(reinterpret_cast<sal_Int64>(pTarget)), 
pTarget->sName);
     m_xControl->set_text(nRow, getTypeName(pTarget->sType), 1);
-    m_xControl->set_text(nRow, pTarget->sContent, 2);
+    m_xControl->set_text(nRow, sContent, 2);
     m_xControl->set_text(nRow, pTarget->bCaseSensitive ? OUString("Yes") : 
OUString("No"), 3);
     m_xControl->set_text(nRow, pTarget->bWholeWords ? OUString("Yes") : 
OUString("No"), 4);
 }
@@ -176,9 +184,17 @@ OUString TargetsTable::GetNameProposal()
 
 void TargetsTable::setRowData(const int& nRowIndex, const RedactionTarget* 
pTarget)
 {
+    OUString sContent = pTarget->sContent;
+
+    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
+    {
+        //selection_num;selection_name
+        sContent = sContent.getToken(1, ';');
+    }
+
     m_xControl->set_text(nRowIndex, pTarget->sName, 0);
     m_xControl->set_text(nRowIndex, getTypeName(pTarget->sType), 1);
-    m_xControl->set_text(nRowIndex, pTarget->sContent, 2);
+    m_xControl->set_text(nRowIndex, sContent, 2);
     m_xControl->set_text(nRowIndex, pTarget->bCaseSensitive ? OUString("Yes") 
: OUString("No"), 3);
     m_xControl->set_text(nRowIndex, pTarget->bWholeWords ? OUString("Yes") : 
OUString("No"), 4);
 }
@@ -600,16 +616,61 @@ bool SfxAutoRedactDialog::moveTargets(
     return true;
 }
 
+IMPL_LINK_NOARG(SfxAddTargetDialog, SelectTypeHdl, weld::ComboBox&, void)
+{
+    if (m_xType->get_active_id() == "predefined")
+    {
+        // Hide the usual content widgets
+        // We will just set the id as content
+        // And handle with proper regex in the SfxRedactionHelper
+        m_xLabelContent->set_sensitive(false);
+        m_xLabelContent->set_visible(false);
+        m_xContent->set_sensitive(false);
+        m_xContent->set_visible(false);
+        m_xWholeWords->set_sensitive(false);
+        m_xWholeWords->set_visible(false);
+        m_xCaseSensitive->set_sensitive(false);
+        m_xCaseSensitive->set_visible(false);
+
+        // And show the predefined targets
+        m_xLabelPredefContent->set_sensitive(true);
+        m_xLabelPredefContent->set_visible(true);
+        m_xPredefContent->set_sensitive(true);
+        m_xPredefContent->set_visible(true);
+    }
+    else
+    {
+        m_xLabelPredefContent->set_sensitive(false);
+        m_xLabelPredefContent->set_visible(false);
+        m_xPredefContent->set_sensitive(false);
+        m_xPredefContent->set_visible(false);
+
+        m_xLabelContent->set_sensitive(true);
+        m_xLabelContent->set_visible(true);
+        m_xContent->set_sensitive(true);
+        m_xContent->set_visible(true);
+        m_xWholeWords->set_sensitive(true);
+        m_xWholeWords->set_visible(true);
+        m_xCaseSensitive->set_sensitive(true);
+        m_xCaseSensitive->set_visible(true);
+    }
+}
+
 SfxAddTargetDialog::SfxAddTargetDialog(weld::Window* pParent, const OUString& 
rName)
     : GenericDialogController(pParent, "sfx/ui/addtargetdialog.ui", 
"AddTargetDialog")
     , m_xName(m_xBuilder->weld_entry("name"))
     , m_xType(m_xBuilder->weld_combo_box("type"))
+    , m_xLabelContent(m_xBuilder->weld_label("label_content"))
     , m_xContent(m_xBuilder->weld_entry("content"))
+    , m_xLabelPredefContent(m_xBuilder->weld_label("label_content_predef"))
+    , m_xPredefContent(m_xBuilder->weld_combo_box("content_predef"))
     , m_xCaseSensitive(m_xBuilder->weld_check_button("checkboxCaseSensitive"))
     , m_xWholeWords(m_xBuilder->weld_check_button("checkboxWholeWords"))
 {
     m_xName->set_text(rName);
     m_xName->select_region(0, rName.getLength());
+
+    m_xType->connect_changed(LINK(this, SfxAddTargetDialog, SelectTypeHdl));
 }
 
 SfxAddTargetDialog::SfxAddTargetDialog(weld::Window* pParent, const OUString& 
sName,
@@ -619,7 +680,10 @@ SfxAddTargetDialog::SfxAddTargetDialog(weld::Window* 
pParent, const OUString& sN
     : GenericDialogController(pParent, "sfx/ui/addtargetdialog.ui", 
"AddTargetDialog")
     , m_xName(m_xBuilder->weld_entry("name"))
     , m_xType(m_xBuilder->weld_combo_box("type"))
+    , m_xLabelContent(m_xBuilder->weld_label("label_content"))
     , m_xContent(m_xBuilder->weld_entry("content"))
+    , m_xLabelPredefContent(m_xBuilder->weld_label("label_content_predef"))
+    , m_xPredefContent(m_xBuilder->weld_combo_box("content_predef"))
     , m_xCaseSensitive(m_xBuilder->weld_check_button("checkboxCaseSensitive"))
     , m_xWholeWords(m_xBuilder->weld_check_button("checkboxWholeWords"))
 {
@@ -628,7 +692,15 @@ SfxAddTargetDialog::SfxAddTargetDialog(weld::Window* 
pParent, const OUString& sN
 
     m_xType->set_active_id(getTypeID(eTargetType));
 
-    m_xContent->set_text(sContent);
+    if (eTargetType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
+    {
+        SelectTypeHdl(*m_xPredefContent);
+        m_xPredefContent->set_active(sContent.getToken(0, ';').toInt32());
+    }
+    else
+    {
+        m_xContent->set_text(sContent);
+    }
 
     m_xCaseSensitive->set_active(bCaseSensitive);
     m_xWholeWords->set_active(bWholeWords);
@@ -650,4 +722,15 @@ RedactionTargetType SfxAddTargetDialog::getType() const
         return RedactionTargetType::REDACTION_TARGET_UNKNOWN;
 }
 
+OUString SfxAddTargetDialog::getContent() const
+{
+    if (m_xType->get_active_id() == "predefined")
+    {
+        return OUString(OUString::number(m_xPredefContent->get_active()) + ";"
+                        + m_xPredefContent->get_active_text());
+    }
+
+    return m_xContent->get_text();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sfx2/uiconfig/ui/addtargetdialog.ui 
b/sfx2/uiconfig/ui/addtargetdialog.ui
index 3d45c7a240bd..d4283222fb65 100644
--- a/sfx2/uiconfig/ui/addtargetdialog.ui
+++ b/sfx2/uiconfig/ui/addtargetdialog.ui
@@ -24,8 +24,8 @@
           <object class="GtkButtonBox">
             <property name="can_focus">False</property>
             <child>
-              <object class="GtkButton" id="cancel">
-                <property name="label">gtk-cancel</property>
+              <object class="GtkButton" id="close">
+                <property name="label">gtk-ok</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -39,8 +39,8 @@
               </packing>
             </child>
             <child>
-              <object class="GtkButton" id="close">
-                <property name="label">gtk-ok</property>
+              <object class="GtkButton" id="cancel">
+                <property name="label">gtk-cancel</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -145,6 +145,7 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="margin_left">2</property>
+                <property name="margin_bottom">2</property>
                 <property name="activates_default">True</property>
                 <accessibility>
                   <relation type="labelled-by" target="label_content"/>
@@ -159,6 +160,9 @@
               <object class="GtkComboBoxText" id="type">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="margin_left">2</property>
+                <property name="margin_bottom">2</property>
+                <property name="active">0</property>
                 <items>
                   <item id="text" translatable="yes" 
context="addtargetdialog|type">Text</item>
                   <item id="regex" translatable="yes" 
context="addtargetdialog|type">Regex</item>
@@ -173,6 +177,44 @@
                 <property name="top_attach">1</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkLabel" id="label_content_predef">
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+                <property name="label" translatable="yes" 
context="addtargetdialog|label_content_predef">Content:</property>
+                <property name="use_underline">True</property>
+                <accessibility>
+                  <relation type="label-for" target="content_predef"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="content_predef">
+                <property name="sensitive">False</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">2</property>
+                <property name="active">0</property>
+                <items>
+                  <item id="creditcard" translatable="yes" 
context="addtargetdialog|content_predef">Credit card numbers</item>
+                  <item id="email" translatable="yes" 
context="addtargetdialog|content_predef">Email addresses</item>
+                  <item id="ip" translatable="yes" 
context="addtargetdialog|content_predef">IP addresses</item>
+                  <item id="numdates" translatable="yes" 
context="addtargetdialog|content_predef">Dates (Numerical)</item>
+                  <item id="uknin" translatable="yes" 
context="addtargetdialog|content_predef">National Insurance Number (UK)</item>
+                  <item id="usssn" translatable="yes" 
context="addtargetdialog|content_predef">Social Security Number (US)</item>
+                </items>
+                <accessibility>
+                  <relation type="labelled-by" target="label_content_predef"/>
+                </accessibility>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">3</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -227,8 +269,8 @@
       </object>
     </child>
     <action-widgets>
-      <action-widget response="-6">cancel</action-widget>
       <action-widget response="-5">close</action-widget>
+      <action-widget response="-6">cancel</action-widget>
       <action-widget response="-11">help</action-widget>
     </action-widgets>
   </object>
commit 9c11b37f6c00cf3f52902089b4af151233879354
Author:     Muhammet Kara <muhammet.k...@collabora.com>
AuthorDate: Thu Jun 13 18:32:27 2019 +0300
Commit:     Muhammet Kara <muhammet.k...@collabora.com>
CommitDate: Mon Jun 17 23:31:15 2019 +0200

    Use utl::TextSearch in the auto redaction process
    
    * Add support for:
      * Case sensitive and insensitive text search
      * Regex search (always case sensitive) regarless of the choice
      * Multiple occurences of the same target on a single TEXTARRAY
    
    Change-Id: I580059f77286e8c4226cafdd1eb9472f8e1a9a9d
    Reviewed-on: https://gerrit.libreoffice.org/74049
    Tested-by: Jenkins
    Reviewed-by: Muhammet Kara <muhammet.k...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/74232
    Tested-by: Muhammet Kara <muhammet.k...@collabora.com>

diff --git a/sfx2/inc/SfxRedactionHelper.hxx b/sfx2/inc/SfxRedactionHelper.hxx
index 9be54ca8ac22..2f470386d2dc 100644
--- a/sfx2/inc/SfxRedactionHelper.hxx
+++ b/sfx2/inc/SfxRedactionHelper.hxx
@@ -33,6 +33,11 @@ class DocumentToGraphicRenderer;
 class SfxViewFrame;
 struct RedactionTarget;
 
+namespace i18nutil
+{
+struct SearchOptions2;
+}
+
 struct PageMargins
 {
     // Page margins in mm100th
@@ -92,7 +97,7 @@ public:
      * */
     static PageMargins 
getPageMarginsForCalc(css::uno::Reference<css::frame::XModel>& xModel);
 
-    static void searchInMetaFile(const OUString& sSearchTerm, const 
GDIMetaFile& rMtf,
+    static void searchInMetaFile(const RedactionTarget* pRedactionTarget, 
const GDIMetaFile& rMtf,
                                  std::vector<tools::Rectangle>& 
aRedactionRectangles,
                                  uno::Reference<XComponent>& xComponent);
 
@@ -111,6 +116,10 @@ public:
                                const GDIMetaFile& rGDIMetaFile,
                                uno::Reference<drawing::XDrawPage>& xPage,
                                uno::Reference<XComponent>& xComponent);
+
+    /// Fill the search options based on the given redaction target
+    static void fillSearchOptions(i18nutil::SearchOptions2& rSearchOpt,
+                                  const RedactionTarget* pTarget);
 };
 
 #endif // INCLUDED_CUI_SOURCE_INC_SFXREDACTIONHELPER_HXX
diff --git a/sfx2/source/doc/SfxRedactionHelper.cxx 
b/sfx2/source/doc/SfxRedactionHelper.cxx
index c5f015ea9d08..75459d093ea9 100644
--- a/sfx2/source/doc/SfxRedactionHelper.cxx
+++ b/sfx2/source/doc/SfxRedactionHelper.cxx
@@ -24,6 +24,18 @@
 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
 
+// Search util
+#include <i18nutil/searchopt.hxx>
+#include <com/sun/star/util/SearchAlgorithms.hpp>
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/util/SearchResult.hpp>
+#include <unotools/configmgr.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <unotools/textsearch.hxx>
+
 #include <sfx2/request.hxx>
 #include <sfx2/sfxsids.hrc>
 #include <sfx2/viewfrm.hxx>
@@ -114,7 +126,7 @@ void setPageMargins(uno::Reference<beans::XPropertySet>& 
xPageProperySet,
 
 // #i10613# Extracted from ImplCheckRect::ImplCreate
 tools::Rectangle ImplCalcActionBounds(const MetaAction& rAct, const 
OutputDevice& rOut,
-                                      const OUString& sSubString, const 
sal_Int32& nStrPos)
+                                      const sal_Int32& nStrStartPos, const 
sal_Int32& nStrEndPos)
 {
     tools::Rectangle aActionBounds;
 
@@ -129,17 +141,16 @@ tools::Rectangle ImplCalcActionBounds(const MetaAction& 
rAct, const OutputDevice
             {
                 // #105987# ImplLayout takes everything in logical coordinates
                 std::unique_ptr<SalLayout> pSalLayout1 = rOut.ImplLayout(
-                    aString, 0, nStrPos, rTextAct.GetPoint(), 0, 
rTextAct.GetDXArray());
-                std::unique_ptr<SalLayout> pSalLayout2
-                    = rOut.ImplLayout(aString, 0, nStrPos + 
sSubString.getLength(),
-                                      rTextAct.GetPoint(), 0, 
rTextAct.GetDXArray());
+                    aString, 0, nStrStartPos, rTextAct.GetPoint(), 0, 
rTextAct.GetDXArray());
+                std::unique_ptr<SalLayout> pSalLayout2 = rOut.ImplLayout(
+                    aString, 0, nStrEndPos, rTextAct.GetPoint(), 0, 
rTextAct.GetDXArray());
                 if (pSalLayout2)
                 {
                     tools::Rectangle aBoundRect2(
                         
const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout2));
                     aActionBounds = rOut.PixelToLogic(aBoundRect2);
                 }
-                if (pSalLayout1 && nStrPos > 0)
+                if (pSalLayout1 && nStrStartPos > 0)
                 {
                     tools::Rectangle aBoundRect1(
                         
const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout1));
@@ -407,10 +418,17 @@ 
SfxRedactionHelper::getPageMarginsForCalc(css::uno::Reference<css::frame::XModel
     return aPageMargins;
 }
 
-void SfxRedactionHelper::searchInMetaFile(const rtl::OUString& sSearchTerm, 
const GDIMetaFile& rMtf,
+void SfxRedactionHelper::searchInMetaFile(const RedactionTarget* 
pRedactionTarget,
+                                          const GDIMetaFile& rMtf,
                                           std::vector<::tools::Rectangle>& 
aRedactionRectangles,
                                           uno::Reference<XComponent>& 
xComponent)
 {
+    // Initialize search
+    i18nutil::SearchOptions2 aSearchOptions;
+    fillSearchOptions(aSearchOptions, pRedactionTarget);
+
+    utl::TextSearch textSearch(aSearchOptions);
+
     MetaAction* pCurrAct;
 
     // Watch for TEXTARRAY actions.
@@ -422,22 +440,28 @@ void SfxRedactionHelper::searchInMetaFile(const 
rtl::OUString& sSearchTerm, cons
         {
             MetaTextArrayAction* pMetaTextArrayAction = 
static_cast<MetaTextArrayAction*>(pCurrAct);
 
-            //sal_Int32 aIndex = pMetaTextArrayAction->GetIndex();
-            //sal_Int32 aLength = pMetaTextArrayAction->GetLen();
-            //Point aPoint = pMetaTextArrayAction->GetPoint();
+            // Search operation takes place here
             OUString sText = pMetaTextArrayAction->GetText();
-            sal_Int32 nFoundIndex = sText.indexOf(sSearchTerm);
+            sal_Int32 nStart = 0;
+            sal_Int32 nEnd = sText.getLength();
+
+            bool bFound = textSearch.SearchForward(sText, &nStart, &nEnd);
 
             // If found the string, add the corresponding rectangle to the 
collection
-            if (nFoundIndex >= 0)
+            while (bFound)
             {
                 OutputDevice* pOutputDevice
                     = 
SfxObjectShell::GetShellFromComponent(xComponent)->GetDocumentRefDev();
-                tools::Rectangle aNewRect(ImplCalcActionBounds(
-                    *pMetaTextArrayAction, *pOutputDevice, sSearchTerm, 
nFoundIndex));
+                tools::Rectangle aNewRect(
+                    ImplCalcActionBounds(*pMetaTextArrayAction, 
*pOutputDevice, nStart, nEnd));
 
                 if (!aNewRect.IsEmpty())
                     aRedactionRectangles.push_back(aNewRect);
+
+                // Search for the next occurence
+                nStart = nEnd;
+                nEnd = sText.getLength();
+                bFound = textSearch.SearchForward(sText, &nStart, &nEnd);
             }
         }
     }
@@ -484,14 +508,48 @@ void SfxRedactionHelper::autoRedactPage(const 
RedactionTarget* pRedactionTarget,
     if (pRedactionTarget == nullptr || pRedactionTarget->sContent.isEmpty())
         return;
 
-    OUString sContent(pRedactionTarget->sContent);
-
     // Search for the redaction strings, and get the rectangle coordinates
     std::vector<::tools::Rectangle> aRedactionRectangles;
-    searchInMetaFile(sContent, rGDIMetaFile, aRedactionRectangles, xComponent);
+    searchInMetaFile(pRedactionTarget, rGDIMetaFile, aRedactionRectangles, 
xComponent);
 
     // Add the redaction rectangles to the page
     addRedactionRectToPage(xComponent, xPage, aRedactionRectangles);
 }
 
+namespace
+{
+const LanguageTag& GetAppLanguageTag() { return 
Application::GetSettings().GetLanguageTag(); }
+}
+
+void SfxRedactionHelper::fillSearchOptions(i18nutil::SearchOptions2& 
rSearchOpt,
+                                           const RedactionTarget* pTarget)
+{
+    if (!pTarget)
+    {
+        SAL_WARN("sfx.doc",
+                 "pTarget (pointer to Redactiontarget) is null. This should 
never happen.");
+        return;
+    }
+
+    if (pTarget->sType == RedactionTargetType::REDACTION_TARGET_REGEX)
+    {
+        rSearchOpt.algorithmType = util::SearchAlgorithms_REGEXP;
+        rSearchOpt.AlgorithmType2 = util::SearchAlgorithms2::REGEXP;
+    }
+    else
+    {
+        rSearchOpt.algorithmType = util::SearchAlgorithms_ABSOLUTE;
+        rSearchOpt.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
+    }
+
+    rSearchOpt.Locale = GetAppLanguageTag().getLocale();
+    rSearchOpt.searchString = pTarget->sContent;
+    rSearchOpt.replaceString.clear();
+
+    if (!pTarget->bCaseSensitive && pTarget->sType != 
RedactionTargetType::REDACTION_TARGET_REGEX)
+        rSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+    if (pTarget->bWholeWords)
+        rSearchOpt.searchFlag |= util::SearchFlags::NORM_WORD_ONLY;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to