1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <SfxRedactionHelper.hxx>
11 #include <autoredactdialog.hxx>
12 
13 #include <com/sun/star/beans/XPropertySet.hpp>
14 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
15 #include <com/sun/star/drawing/LineStyle.hpp>
16 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
17 #include <com/sun/star/graphic/XGraphic.hpp>
18 #include <com/sun/star/frame/XLayoutManager.hpp>
19 
20 // For page margin related methods
21 #include <com/sun/star/style/XStyle.hpp>
22 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
23 #include <com/sun/star/text/XPageCursor.hpp>
24 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
25 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
26 
27 // Search util
28 #include <i18nutil/searchopt.hxx>
29 #include <com/sun/star/util/SearchAlgorithms.hpp>
30 #include <com/sun/star/util/SearchAlgorithms2.hpp>
31 #include <com/sun/star/util/SearchFlags.hpp>
32 #include <vcl/svapp.hxx>
33 #include <vcl/settings.hxx>
34 #include <i18nlangtag/languagetag.hxx>
35 #include <unotools/textsearch.hxx>
36 
37 #include <sfx2/request.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <sfx2/viewfrm.hxx>
40 
41 #include <svl/eitem.hxx>
42 #include <svl/stritem.hxx>
43 
44 #include <svtools/DocumentToGraphicRenderer.hxx>
45 
46 #include <tools/gen.hxx>
47 #include <tools/stream.hxx>
48 #include <tools/diagnose_ex.h>
49 
50 #include <vcl/gdimtf.hxx>
51 #include <vcl/graph.hxx>
52 #include <sal/log.hxx>
53 
54 #include <vcl/wmf.hxx>
55 #include <vcl/metaact.hxx>
56 #include <vcl/outdev.hxx>
57 #include <vcl/vcllayout.hxx>
58 
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::lang;
61 using namespace ::com::sun::star::uno;
62 
isRedactMode(const SfxRequest & rReq)63 bool SfxRedactionHelper::isRedactMode(const SfxRequest& rReq)
64 {
65     const SfxItemSet* pArgs = rReq.GetArgs();
66     if (pArgs)
67     {
68         const SfxBoolItem* pIsRedactMode = rReq.GetArg<SfxBoolItem>(SID_IS_REDACT_MODE);
69         if (pIsRedactMode && pIsRedactMode->GetValue())
70             return true;
71     }
72 
73     return false;
74 }
75 
getStringParam(const SfxRequest & rReq,sal_uInt16 nParamId)76 OUString SfxRedactionHelper::getStringParam(const SfxRequest& rReq, sal_uInt16 nParamId)
77 {
78     OUString sStringParam;
79 
80     const SfxItemSet* pArgs = rReq.GetArgs();
81     if (!pArgs)
82         return sStringParam;
83 
84     const SfxStringItem* pStringArg = rReq.GetArg<SfxStringItem>(nParamId);
85     if (!pStringArg)
86         return sStringParam;
87 
88     sStringParam = pStringArg->GetValue();
89     return sStringParam;
90 }
91 
92 namespace
93 {
94 /*
95  * Roundtrip the gdimetafile to and from WMF
96  * to get rid of the position and size irregularities
97  * We better check the conversion method to see what it
98  * actually does to correct these issues, and do it ourselves.
99  * */
fixMetaFile(GDIMetaFile & tmpMtf)100 void fixMetaFile(GDIMetaFile& tmpMtf)
101 {
102     SvMemoryStream aDestStrm(65535, 65535);
103     ConvertGDIMetaFileToWMF(tmpMtf, aDestStrm, nullptr, false);
104     aDestStrm.Seek(0);
105 
106     tmpMtf.Clear();
107 
108     ReadWindowMetafile(aDestStrm, tmpMtf);
109 }
110 
111 /*
112  * Sets page margins for a Draw page. Negative values are considered erroneous
113  * */
setPageMargins(const uno::Reference<beans::XPropertySet> & xPageProperySet,const PageMargins & aPageMargins)114 void setPageMargins(const uno::Reference<beans::XPropertySet>& xPageProperySet,
115                     const PageMargins& aPageMargins)
116 {
117     if (aPageMargins.nTop < 0 || aPageMargins.nBottom < 0 || aPageMargins.nLeft < 0
118         || aPageMargins.nRight < 0)
119         return;
120 
121     xPageProperySet->setPropertyValue("BorderTop", css::uno::makeAny(aPageMargins.nTop));
122     xPageProperySet->setPropertyValue("BorderBottom", css::uno::makeAny(aPageMargins.nBottom));
123     xPageProperySet->setPropertyValue("BorderLeft", css::uno::makeAny(aPageMargins.nLeft));
124     xPageProperySet->setPropertyValue("BorderRight", css::uno::makeAny(aPageMargins.nRight));
125 }
126 
127 // #i10613# Extracted from ImplCheckRect::ImplCreate
ImplCalcActionBounds(const MetaAction & rAct,const OutputDevice & rOut,sal_Int32 nStrStartPos,sal_Int32 nStrEndPos)128 tools::Rectangle ImplCalcActionBounds(const MetaAction& rAct, const OutputDevice& rOut,
129                                       sal_Int32 nStrStartPos, sal_Int32 nStrEndPos)
130 {
131     tools::Rectangle aActionBounds;
132 
133     switch (rAct.GetType())
134     {
135         case MetaActionType::TEXTARRAY:
136         {
137             const MetaTextArrayAction& rTextAct = static_cast<const MetaTextArrayAction&>(rAct);
138             const OUString aString(rTextAct.GetText().copy(rTextAct.GetIndex(), rTextAct.GetLen()));
139 
140             if (!aString.isEmpty())
141             {
142                 // #105987# ImplLayout takes everything in logical coordinates
143                 std::unique_ptr<SalLayout> pSalLayout1 = rOut.ImplLayout(
144                     aString, 0, nStrStartPos, rTextAct.GetPoint(), 0, rTextAct.GetDXArray());
145                 std::unique_ptr<SalLayout> pSalLayout2 = rOut.ImplLayout(
146                     aString, 0, nStrEndPos, rTextAct.GetPoint(), 0, rTextAct.GetDXArray());
147                 if (pSalLayout2)
148                 {
149                     tools::Rectangle aBoundRect2(
150                         const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout2));
151                     aActionBounds = rOut.PixelToLogic(aBoundRect2);
152                 }
153                 if (pSalLayout1 && nStrStartPos > 0)
154                 {
155                     tools::Rectangle aBoundRect1(
156                         const_cast<OutputDevice&>(rOut).ImplGetTextBoundRect(*pSalLayout1));
157                     aActionBounds.SetLeft(rOut.PixelToLogic(aBoundRect1).getX()
158                                           + rOut.PixelToLogic(aBoundRect1).getWidth());
159                 }
160             }
161         }
162         break;
163 
164         default:
165             break;
166     }
167 
168     if (!aActionBounds.IsEmpty())
169     {
170         // fdo#40421 limit current action's output to clipped area
171         if (rOut.IsClipRegion())
172             return rOut.GetClipRegion().GetBoundRect().Intersection(aActionBounds);
173         else
174             return aActionBounds;
175     }
176     else
177         return aActionBounds;
178 }
179 
180 } // End of anon namespace
181 
getPageMetaFilesFromDoc(std::vector<GDIMetaFile> & aMetaFiles,std::vector<::Size> & aPageSizes,sal_Int32 nPages,DocumentToGraphicRenderer & aRenderer)182 void SfxRedactionHelper::getPageMetaFilesFromDoc(std::vector<GDIMetaFile>& aMetaFiles,
183                                                  std::vector<::Size>& aPageSizes, sal_Int32 nPages,
184                                                  DocumentToGraphicRenderer& aRenderer)
185 {
186     for (sal_Int32 nPage = 1; nPage <= nPages; ++nPage)
187     {
188         ::Size aDocumentSizePixel = aRenderer.getDocumentSizeInPixels(nPage);
189         ::Point aLogicPos;
190         ::Point aCalcPageLogicPos;
191         ::Size aCalcPageContentSize;
192         ::Size aLogic = aRenderer.getDocumentSizeIn100mm(nPage, &aLogicPos, &aCalcPageLogicPos,
193                                                          &aCalcPageContentSize);
194 
195         aPageSizes.push_back(aLogic);
196 
197         Graphic aGraphic = aRenderer.renderToGraphic(nPage, aDocumentSizePixel, aDocumentSizePixel,
198                                                      COL_TRANSPARENT, true);
199         auto& rGDIMetaFile = const_cast<GDIMetaFile&>(aGraphic.GetGDIMetaFile());
200 
201         // Set preferred map unit and size on the metafile, so the Shape size
202         // will be correct in MM.
203         MapMode aMapMode;
204         aMapMode.SetMapUnit(MapUnit::Map100thMM);
205 
206         rGDIMetaFile.SetPrefMapMode(aMapMode);
207         rGDIMetaFile.SetPrefSize(aLogic);
208 
209         fixMetaFile(rGDIMetaFile);
210 
211         aMetaFiles.push_back(rGDIMetaFile);
212     }
213 }
214 
addPagesToDraw(const uno::Reference<XComponent> & xComponent,sal_Int32 nPages,const std::vector<GDIMetaFile> & aMetaFiles,const std::vector<::Size> & aPageSizes,const PageMargins & aPageMargins,const std::vector<std::pair<RedactionTarget,OUString>> & r_aTableTargets,bool bIsAutoRedact)215 void SfxRedactionHelper::addPagesToDraw(
216     const uno::Reference<XComponent>& xComponent, sal_Int32 nPages,
217     const std::vector<GDIMetaFile>& aMetaFiles, const std::vector<::Size>& aPageSizes,
218     const PageMargins& aPageMargins,
219     const std::vector<std::pair<RedactionTarget, OUString>>& r_aTableTargets, bool bIsAutoRedact)
220 {
221     // Access the draw pages
222     uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(xComponent, uno::UNO_QUERY);
223     uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages();
224 
225     uno::Reference<css::lang::XMultiServiceFactory> xFactory(xComponent, uno::UNO_QUERY);
226 
227     for (sal_Int32 nPage = 0; nPage < nPages; ++nPage)
228     {
229         GDIMetaFile rGDIMetaFile = aMetaFiles[nPage];
230         Graphic aGraphic(rGDIMetaFile);
231 
232         sal_Int32 nPageHeight(aPageSizes[nPage].Height());
233         sal_Int32 nPageWidth(aPageSizes[nPage].Width());
234 
235         uno::Reference<graphic::XGraphic> xGraph = aGraphic.GetXGraphic();
236         uno::Reference<drawing::XDrawPage> xPage = xDrawPages->insertNewByIndex(nPage);
237 
238         // Set page size & margins
239         uno::Reference<beans::XPropertySet> xPageProperySet(xPage, uno::UNO_QUERY);
240         xPageProperySet->setPropertyValue("Height", css::uno::makeAny(nPageHeight));
241         xPageProperySet->setPropertyValue("Width", css::uno::makeAny(nPageWidth));
242 
243         setPageMargins(xPageProperySet, aPageMargins);
244 
245         // Create and insert the shape
246         uno::Reference<drawing::XShape> xShape(
247             xFactory->createInstance("com.sun.star.drawing.GraphicObjectShape"), uno::UNO_QUERY);
248         uno::Reference<beans::XPropertySet> xShapeProperySet(xShape, uno::UNO_QUERY);
249         xShapeProperySet->setPropertyValue("Graphic", uno::Any(xGraph));
250         xShapeProperySet->setPropertyValue("MoveProtect", uno::Any(true));
251         xShapeProperySet->setPropertyValue("SizeProtect", uno::Any(true));
252 
253         // Set size
254         xShape->setSize(
255             awt::Size(rGDIMetaFile.GetPrefSize().Width(), rGDIMetaFile.GetPrefSize().Height()));
256 
257         xPage->add(xShape);
258 
259         if (bIsAutoRedact && !r_aTableTargets.empty())
260         {
261             for (const auto& targetPair : r_aTableTargets)
262             {
263                 autoRedactPage(targetPair.first, rGDIMetaFile, xPage, xComponent);
264             }
265         }
266     }
267 
268     // Remove the extra page at the beginning
269     uno::Reference<drawing::XDrawPage> xPage(xDrawPages->getByIndex(0), uno::UNO_QUERY_THROW);
270     xDrawPages->remove(xPage);
271 }
272 
showRedactionToolbar(const SfxViewFrame * pViewFrame)273 void SfxRedactionHelper::showRedactionToolbar(const SfxViewFrame* pViewFrame)
274 {
275     if (!pViewFrame)
276         return;
277 
278     Reference<frame::XFrame> xFrame = pViewFrame->GetFrame().GetFrameInterface();
279     Reference<css::beans::XPropertySet> xPropSet(xFrame, UNO_QUERY);
280     Reference<css::frame::XLayoutManager> xLayoutManager;
281 
282     if (!xPropSet.is())
283         return;
284 
285     try
286     {
287         Any aValue = xPropSet->getPropertyValue("LayoutManager");
288         aValue >>= xLayoutManager;
289         xLayoutManager->createElement("private:resource/toolbar/redactionbar");
290         xLayoutManager->showElement("private:resource/toolbar/redactionbar");
291     }
292     catch (const css::uno::RuntimeException&)
293     {
294         throw;
295     }
296     catch (css::uno::Exception&)
297     {
298         TOOLS_WARN_EXCEPTION("sfx.doc", "Exception while trying to show the Redaction Toolbar!");
299     }
300 }
301 
302 PageMargins
getPageMarginsForWriter(const css::uno::Reference<css::frame::XModel> & xModel)303 SfxRedactionHelper::getPageMarginsForWriter(const css::uno::Reference<css::frame::XModel>& xModel)
304 {
305     PageMargins aPageMargins = { -1, -1, -1, -1 };
306 
307     Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xModel->getCurrentController(),
308                                                                      UNO_QUERY);
309     if (!xTextViewCursorSupplier.is())
310     {
311         SAL_WARN("sfx.doc", "Ref to xTextViewCursorSupplier is null in setPageMargins().");
312         return aPageMargins;
313     }
314 
315     Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), UNO_QUERY);
316 
317     uno::Reference<beans::XPropertySet> xPageProperySet(xCursor, UNO_QUERY);
318     OUString sPageStyleName;
319     Any aValue = xPageProperySet->getPropertyValue("PageStyleName");
320     aValue >>= sPageStyleName;
321 
322     Reference<css::style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, UNO_QUERY);
323     if (!xStyleFamiliesSupplier.is())
324     {
325         SAL_WARN("sfx.doc", "Ref to xStyleFamiliesSupplier is null in setPageMargins().");
326         return aPageMargins;
327     }
328     uno::Reference<container::XNameAccess> xStyleFamilies
329         = xStyleFamiliesSupplier->getStyleFamilies();
330 
331     if (!xStyleFamilies.is())
332         return aPageMargins;
333 
334     uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"),
335                                                        UNO_QUERY);
336 
337     if (!xPageStyles.is())
338         return aPageMargins;
339 
340     uno::Reference<css::style::XStyle> xPageStyle(xPageStyles->getByName(sPageStyleName),
341                                                   UNO_QUERY);
342 
343     if (!xPageStyle.is())
344         return aPageMargins;
345 
346     uno::Reference<beans::XPropertySet> xPageProperties(xPageStyle, uno::UNO_QUERY);
347 
348     if (!xPageProperties.is())
349         return aPageMargins;
350 
351     xPageProperties->getPropertyValue("LeftMargin") >>= aPageMargins.nLeft;
352     xPageProperties->getPropertyValue("RightMargin") >>= aPageMargins.nRight;
353     xPageProperties->getPropertyValue("TopMargin") >>= aPageMargins.nTop;
354     xPageProperties->getPropertyValue("BottomMargin") >>= aPageMargins.nBottom;
355 
356     return aPageMargins;
357 }
358 
359 PageMargins
getPageMarginsForCalc(const css::uno::Reference<css::frame::XModel> & xModel)360 SfxRedactionHelper::getPageMarginsForCalc(const css::uno::Reference<css::frame::XModel>& xModel)
361 {
362     PageMargins aPageMargins = { -1, -1, -1, -1 };
363     OUString sPageStyleName("Default");
364 
365     css::uno::Reference<css::sheet::XSpreadsheetView> xSpreadsheetView(
366         xModel->getCurrentController(), UNO_QUERY);
367 
368     if (!xSpreadsheetView.is())
369     {
370         SAL_WARN("sfx.doc", "Ref to xSpreadsheetView is null in getPageMarginsForCalc().");
371         return aPageMargins;
372     }
373 
374     uno::Reference<beans::XPropertySet> xSheetProperties(xSpreadsheetView->getActiveSheet(),
375                                                          UNO_QUERY);
376 
377     xSheetProperties->getPropertyValue("PageStyle") >>= sPageStyleName;
378 
379     Reference<css::style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(xModel, UNO_QUERY);
380     if (!xStyleFamiliesSupplier.is())
381     {
382         SAL_WARN("sfx.doc", "Ref to xStyleFamiliesSupplier is null in getPageMarginsForCalc().");
383         return aPageMargins;
384     }
385     uno::Reference<container::XNameAccess> xStyleFamilies
386         = xStyleFamiliesSupplier->getStyleFamilies();
387 
388     if (!xStyleFamilies.is())
389         return aPageMargins;
390 
391     uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"),
392                                                        UNO_QUERY);
393 
394     if (!xPageStyles.is())
395         return aPageMargins;
396 
397     uno::Reference<css::style::XStyle> xPageStyle(xPageStyles->getByName(sPageStyleName),
398                                                   UNO_QUERY);
399 
400     if (!xPageStyle.is())
401         return aPageMargins;
402 
403     uno::Reference<beans::XPropertySet> xPageProperties(xPageStyle, uno::UNO_QUERY);
404 
405     if (!xPageProperties.is())
406         return aPageMargins;
407 
408     xPageProperties->getPropertyValue("LeftMargin") >>= aPageMargins.nLeft;
409     xPageProperties->getPropertyValue("RightMargin") >>= aPageMargins.nRight;
410     xPageProperties->getPropertyValue("TopMargin") >>= aPageMargins.nTop;
411     xPageProperties->getPropertyValue("BottomMargin") >>= aPageMargins.nBottom;
412 
413     return aPageMargins;
414 }
415 
searchInMetaFile(const RedactionTarget & rRedactionTarget,const GDIMetaFile & rMtf,std::vector<::tools::Rectangle> & aRedactionRectangles,const uno::Reference<XComponent> & xComponent)416 void SfxRedactionHelper::searchInMetaFile(const RedactionTarget& rRedactionTarget,
417                                           const GDIMetaFile& rMtf,
418                                           std::vector<::tools::Rectangle>& aRedactionRectangles,
419                                           const uno::Reference<XComponent>& xComponent)
420 {
421     // Initialize search
422     i18nutil::SearchOptions2 aSearchOptions;
423     fillSearchOptions(aSearchOptions, rRedactionTarget);
424 
425     utl::TextSearch textSearch(aSearchOptions);
426     static tools::Long aLastFontHeight = 0;
427 
428     MetaAction* pCurrAct;
429 
430     for (pCurrAct = const_cast<GDIMetaFile&>(rMtf).FirstAction(); pCurrAct;
431          pCurrAct = const_cast<GDIMetaFile&>(rMtf).NextAction())
432     {
433         // Watch for TEXTARRAY actions.
434         // They contain the text of paragraphs.
435         if (pCurrAct->GetType() == MetaActionType::TEXTARRAY)
436         {
437             MetaTextArrayAction* pMetaTextArrayAction = static_cast<MetaTextArrayAction*>(pCurrAct);
438 
439             // Search operation takes place here
440             OUString sText = pMetaTextArrayAction->GetText();
441             sal_Int32 nStart = 0;
442             sal_Int32 nEnd = sText.getLength();
443 
444             bool bFound = textSearch.SearchForward(sText, &nStart, &nEnd);
445 
446             // If found the string, add the corresponding rectangle to the collection
447             while (bFound)
448             {
449                 OutputDevice* pOutputDevice
450                     = SfxObjectShell::GetShellFromComponent(xComponent)->GetDocumentRefDev();
451                 tools::Rectangle aNewRect(
452                     ImplCalcActionBounds(*pMetaTextArrayAction, *pOutputDevice, nStart, nEnd));
453 
454                 if (!aNewRect.IsEmpty())
455                 {
456                     // Calculate the difference between current wrong value and value should it be.
457                     // Add the difference to current value.
458                     // Then increase 10% of the new value to make it look better.
459                     aNewRect.SetTop(aNewRect.getY() + (aNewRect.getHeight() - aLastFontHeight)
460                                     - aLastFontHeight / 10);
461                     aRedactionRectangles.push_back(aNewRect);
462                 }
463 
464                 // Search for the next occurrence
465                 nStart = nEnd;
466                 nEnd = sText.getLength();
467                 bFound = textSearch.SearchForward(sText, &nStart, &nEnd);
468             }
469         }
470         else if (pCurrAct->GetType() == MetaActionType::FONT)
471         {
472             const MetaFontAction* pFontAct = static_cast<const MetaFontAction*>(pCurrAct);
473             aLastFontHeight = pFontAct->GetFont().GetFontSize().getHeight();
474         }
475     }
476 }
477 
addRedactionRectToPage(const uno::Reference<XComponent> & xComponent,const uno::Reference<drawing::XDrawPage> & xPage,const std::vector<::tools::Rectangle> & aNewRectangles)478 void SfxRedactionHelper::addRedactionRectToPage(
479     const uno::Reference<XComponent>& xComponent, const uno::Reference<drawing::XDrawPage>& xPage,
480     const std::vector<::tools::Rectangle>& aNewRectangles)
481 {
482     if (!xComponent.is() || !xPage.is())
483         return;
484 
485     if (aNewRectangles.empty())
486         return;
487 
488     uno::Reference<css::lang::XMultiServiceFactory> xFactory(xComponent, uno::UNO_QUERY);
489 
490     for (auto const& aNewRectangle : aNewRectangles)
491     {
492         uno::Reference<drawing::XShape> xRectShape(
493             xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
494         uno::Reference<beans::XPropertySet> xRectShapeProperySet(xRectShape, uno::UNO_QUERY);
495 
496         xRectShapeProperySet->setPropertyValue("Name",
497                                                uno::Any(OUString("RectangleRedactionShape")));
498         xRectShapeProperySet->setPropertyValue("FillTransparence",
499                                                css::uno::makeAny(static_cast<sal_Int16>(50)));
500         xRectShapeProperySet->setPropertyValue("FillColor", css::uno::makeAny(COL_GRAY7));
501         xRectShapeProperySet->setPropertyValue(
502             "LineStyle", css::uno::makeAny(css::drawing::LineStyle::LineStyle_NONE));
503 
504         xRectShape->setSize(awt::Size(aNewRectangle.GetWidth(), aNewRectangle.GetHeight()));
505         xRectShape->setPosition(awt::Point(aNewRectangle.getX(), aNewRectangle.getY()));
506 
507         xPage->add(xRectShape);
508     }
509 }
510 
autoRedactPage(const RedactionTarget & rRedactionTarget,const GDIMetaFile & rGDIMetaFile,const uno::Reference<drawing::XDrawPage> & xPage,const uno::Reference<XComponent> & xComponent)511 void SfxRedactionHelper::autoRedactPage(const RedactionTarget& rRedactionTarget,
512                                         const GDIMetaFile& rGDIMetaFile,
513                                         const uno::Reference<drawing::XDrawPage>& xPage,
514                                         const uno::Reference<XComponent>& xComponent)
515 {
516     if (rRedactionTarget.sContent.isEmpty())
517         return;
518 
519     // Search for the redaction strings, and get the rectangle coordinates
520     std::vector<::tools::Rectangle> aRedactionRectangles;
521     searchInMetaFile(rRedactionTarget, rGDIMetaFile, aRedactionRectangles, xComponent);
522 
523     // Add the redaction rectangles to the page
524     addRedactionRectToPage(xComponent, xPage, aRedactionRectangles);
525 }
526 
527 namespace
528 {
GetAppLanguageTag()529 const LanguageTag& GetAppLanguageTag() { return Application::GetSettings().GetLanguageTag(); }
530 }
531 
fillSearchOptions(i18nutil::SearchOptions2 & rSearchOpt,const RedactionTarget & rTarget)532 void SfxRedactionHelper::fillSearchOptions(i18nutil::SearchOptions2& rSearchOpt,
533                                            const RedactionTarget& rTarget)
534 {
535     if (rTarget.sType == RedactionTargetType::REDACTION_TARGET_REGEX
536         || rTarget.sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
537     {
538         rSearchOpt.algorithmType = util::SearchAlgorithms_REGEXP;
539         rSearchOpt.AlgorithmType2 = util::SearchAlgorithms2::REGEXP;
540     }
541     else
542     {
543         rSearchOpt.algorithmType = util::SearchAlgorithms_ABSOLUTE;
544         rSearchOpt.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
545     }
546 
547     rSearchOpt.Locale = GetAppLanguageTag().getLocale();
548     if (rTarget.sType == RedactionTargetType::REDACTION_TARGET_PREDEFINED)
549     {
550         auto nPredefIndex = rTarget.sContent.getToken(0, ';').toUInt32();
551         rSearchOpt.searchString = m_aPredefinedTargets[nPredefIndex];
552     }
553     else
554         rSearchOpt.searchString = rTarget.sContent;
555 
556     rSearchOpt.replaceString.clear();
557 
558     if (!rTarget.bCaseSensitive && rTarget.sType != RedactionTargetType::REDACTION_TARGET_REGEX
559         && rTarget.sType != RedactionTargetType::REDACTION_TARGET_PREDEFINED)
560         rSearchOpt.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
561     if (rTarget.bWholeWords)
562         rSearchOpt.searchFlag |= util::SearchFlags::NORM_WORD_ONLY;
563 }
564 
565 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
566