sc/inc/postit.hxx                       |   20 ++++--
 sc/source/core/data/postit.cxx          |   52 ++++++++---------
 sc/source/filter/inc/richstring.hxx     |    3 +
 sc/source/filter/oox/commentsbuffer.cxx |   94 +++++++++++++++++++++-----------
 sc/source/filter/oox/richstring.cxx     |   14 +++-
 sc/source/ui/docshell/docfunc.cxx       |    9 +--
 sc/source/ui/inc/docfunc.hxx            |   10 ++-
 7 files changed, 126 insertions(+), 76 deletions(-)

New commits:
commit 2bda87fd8758448267c447ba26f1932325a1338d
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Fri Aug 11 13:29:23 2023 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Sun Aug 13 18:13:20 2023 +0200

    defer turning xlsx notes into SdrCaptions until activated
    
    to improve import performance
    
    Change-Id: I8dd3483372d20cbbb8694bae02a7d8b062324ff0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155613
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/inc/postit.hxx b/sc/inc/postit.hxx
index c2a5cc9a60ad..df114eaf64a5 100644
--- a/sc/inc/postit.hxx
+++ b/sc/inc/postit.hxx
@@ -174,12 +174,20 @@ private:
     sal_uInt32          mnPostItId;
 };
 
+class GenerateNoteCaption
+{
+public:
+    virtual void Generate(SdrCaptionObj& rCaptionObj) = 0;
+    virtual OUString GetSimpleText() const = 0;
+    virtual ~GenerateNoteCaption() {};
+};
+
 class SC_DLLPUBLIC ScNoteUtil
 {
     static ScPostIt* InsertNote(ScDocument& rDoc, const ScAddress& rPos, 
ScNoteData&& rNoteData,
                                 bool bAlwaysCreateCaption, sal_uInt32 
nPostItId);
 
-    static ScNoteData CreateNoteData(ScDocument& rDoc, const ScAddress& rPos, 
const OutlinerParaObject& rOutlinerObj,
+    static ScNoteData CreateNoteData(ScDocument& rDoc, const ScAddress& rPos,
                                      const tools::Rectangle& rCaptionRect, 
bool bShown);
 public:
 
@@ -242,13 +250,11 @@ public:
                             const OutlinerParaObject& rOutlinerObj,
                             const tools::Rectangle& rCaptionRect, bool bShown 
);
 
-    // similar to above, except rPropertyNames/rPropertyValues contain the
-    // uno properties for the caption object formatting.
-    static ScPostIt*    CreateNoteFromObjectProperties(
+    // similar to above, except xGenerator is a functor to apply import
+    // properties to the caption object to finalize it on demand
+    static ScPostIt*    CreateNoteFromGenerator(
                             ScDocument& rDoc, const ScAddress& rPos,
-                            const css::uno::Sequence<OUString>& rPropertyNames,
-                            const css::uno::Sequence<css::uno::Any>& 
rPropertyValues,
-                            const OutlinerParaObject& rOutlinerObj,
+                            std::unique_ptr<GenerateNoteCaption> xGenerator,
                             const tools::Rectangle& rCaptionRect, bool bShown 
);
 
     /** Creates a cell note based on the passed string and inserts it into the
diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx
index cdcc03e4999d..b631d7659d99 100644
--- a/sc/source/core/data/postit.cxx
+++ b/sc/source/core/data/postit.cxx
@@ -424,15 +424,11 @@ ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& 
rDoc, const ScAddress& r
 
 } // namespace
 
-
 struct ScCaptionInitData
 {
     std::optional< SfxItemSet > moItemSet;  /// Caption object formatting.
-
-    uno::Sequence<OUString> maPropertyNames; /// Alternative import filter 
Caption object formatting property names
-    uno::Sequence<uno::Any> maPropertyValues; /// Alternative import filter 
Caption object formatting property values
-
     std::optional< OutlinerParaObject > mxOutlinerObj; /// Text object with 
all text portion formatting.
+    std::unique_ptr< GenerateNoteCaption > mxGenerator; /// Operator to 
generate Caption Object from import data
     OUString            maStyleName;        /// Drawing style associated with 
the caption object.
     OUString            maSimpleText;       /// Simple text without formatting.
     Point               maCaptionOffset;    /// Caption position relative to 
cell corner.
@@ -658,13 +654,18 @@ void ScPostIt::CreateCaptionFromInitData( const 
ScAddress& rPos ) const
     bool bWasLocked = 
maNoteData.mxCaption->getSdrModelFromSdrObject().isLocked();
     maNoteData.mxCaption->getSdrModelFromSdrObject().setLock(true);
 
-    // transfer ownership of outliner object to caption, or set simple text
-    OSL_ENSURE( xInitData->mxOutlinerObj || !xInitData->maSimpleText.isEmpty(),
-        "ScPostIt::CreateCaptionFromInitData - need either outliner para 
object or simple text" );
-    if (xInitData->mxOutlinerObj)
-        maNoteData.mxCaption->SetOutlinerParaObject( 
std::move(xInitData->mxOutlinerObj) );
+    if (xInitData->mxGenerator)
+        xInitData->mxGenerator->Generate(*maNoteData.mxCaption);
     else
-        maNoteData.mxCaption->SetText( xInitData->maSimpleText );
+    {
+        // transfer ownership of outliner object to caption, or set simple text
+        OSL_ENSURE( xInitData->mxOutlinerObj || 
!xInitData->maSimpleText.isEmpty(),
+            "ScPostIt::CreateCaptionFromInitData - need either outliner para 
object or simple text" );
+        if (xInitData->mxOutlinerObj)
+            maNoteData.mxCaption->SetOutlinerParaObject( 
std::move(xInitData->mxOutlinerObj) );
+        else
+            maNoteData.mxCaption->SetText( xInitData->maSimpleText );
+    }
 
     if (!xInitData->maStyleName.isEmpty())
     {
@@ -684,13 +685,6 @@ void ScPostIt::CreateCaptionFromInitData( const ScAddress& 
rPos ) const
             ScCaptionUtil::SetExtraItems(*maNoteData.mxCaption, 
*xInitData->moItemSet);
     }
 
-    if (xInitData->maPropertyNames.getLength())
-    {
-        rtl::Reference<SvxShapeText> 
xAnnoShape(dynamic_cast<SvxShapeText*>(maNoteData.mxCaption->getUnoShape().get()));
 // SvxShapeText
-        assert(xAnnoShape && "will not be null");
-        
static_cast<SvxShape*>(xAnnoShape.get())->setPropertyValues(xInitData->maPropertyNames,
 xInitData->maPropertyValues);
-    }
-
     // set position and size of the caption object
     if( xInitData->mbDefaultPosSize )
     {
@@ -941,13 +935,12 @@ ScPostIt* ScNoteUtil::CreateNoteFromCaption(
     return pNote;
 }
 
-ScNoteData ScNoteUtil::CreateNoteData(ScDocument& rDoc, const ScAddress& rPos, 
const OutlinerParaObject& rOutlinerObj,
+ScNoteData ScNoteUtil::CreateNoteData(ScDocument& rDoc, const ScAddress& rPos,
                                       const tools::Rectangle& rCaptionRect, 
bool bShown)
 {
     ScNoteData aNoteData( bShown );
     aNoteData.mxInitData = std::make_shared<ScCaptionInitData>();
     ScCaptionInitData& rInitData = *aNoteData.mxInitData;
-    rInitData.mxOutlinerObj = rOutlinerObj;
 
     // convert absolute caption position to relative position
     rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty();
@@ -968,25 +961,28 @@ ScPostIt* ScNoteUtil::CreateNoteFromObjectData(
         const OutlinerParaObject& rOutlinerObj, const tools::Rectangle& 
rCaptionRect,
         bool bShown )
 {
-    ScNoteData aNoteData(CreateNoteData(rDoc, rPos, rOutlinerObj, 
rCaptionRect, bShown));
+    ScNoteData aNoteData(CreateNoteData(rDoc, rPos, rCaptionRect, bShown));
     ScCaptionInitData& rInitData = *aNoteData.mxInitData;
+    rInitData.mxOutlinerObj = rOutlinerObj;
     rInitData.moItemSet.emplace(std::move(rItemSet));
     rInitData.maStyleName = 
ScStyleNameConversion::ProgrammaticToDisplayName(rStyleName, 
SfxStyleFamily::Frame);
 
     return InsertNote(rDoc, rPos, std::move(aNoteData), 
/*bAlwaysCreateCaption*/false, 0/*nPostItId*/);
 }
 
-ScPostIt* ScNoteUtil::CreateNoteFromObjectProperties(
+ScPostIt* ScNoteUtil::CreateNoteFromGenerator(
         ScDocument& rDoc, const ScAddress& rPos,
-        const uno::Sequence<OUString>& rPropertyNames,
-        const uno::Sequence<uno::Any>& rPropertyValues,
-        const OutlinerParaObject& rOutlinerObj, const tools::Rectangle& 
rCaptionRect,
+        std::unique_ptr<GenerateNoteCaption> xGenerator,
+        const tools::Rectangle& rCaptionRect,
         bool bShown )
 {
-    ScNoteData aNoteData(CreateNoteData(rDoc, rPos, rOutlinerObj, 
rCaptionRect, bShown));
+    ScNoteData aNoteData(CreateNoteData(rDoc, rPos, rCaptionRect, bShown));
     ScCaptionInitData& rInitData = *aNoteData.mxInitData;
-    rInitData.maPropertyNames = rPropertyNames;
-    rInitData.maPropertyValues = rPropertyValues;
+    rInitData.mxGenerator = std::move(xGenerator);
+    // because the Caption is generated on demand, we will need to create the
+    // simple text now to supply any querys for that which don't require
+    // creation of a full Caption
+    rInitData.maSimpleText = rInitData.mxGenerator->GetSimpleText();
 
     return InsertNote(rDoc, rPos, std::move(aNoteData), 
/*bAlwaysCreateCaption*/false, 0/*nPostItId*/);
 }
diff --git a/sc/source/filter/inc/richstring.hxx 
b/sc/source/filter/inc/richstring.hxx
index b74e3036f473..3969de6b7974 100644
--- a/sc/source/filter/inc/richstring.hxx
+++ b/sc/source/filter/inc/richstring.hxx
@@ -228,6 +228,9 @@ public:
                             OUString& orString,
                             const oox::xls::Font* pFirstPortionFont ) const;
 
+    /** Get the text of all portions as a single string regardless of 
formatted or not */
+    OUString            getStringContent() const;
+
     /** Converts the string and writes it into the passed XText, replace old 
contents of the text object,.
         @param rxText  The XText interface of the target object.
      */
diff --git a/sc/source/filter/oox/commentsbuffer.cxx 
b/sc/source/filter/oox/commentsbuffer.cxx
index 9307ad707006..1f1f2dd2540c 100644
--- a/sc/source/filter/oox/commentsbuffer.cxx
+++ b/sc/source/filter/oox/commentsbuffer.cxx
@@ -147,6 +147,44 @@ RichStringRef const & Comment::createText()
     return maModel.mxText;
 }
 
+namespace
+{
+    struct OOXGenerateNoteCaption : public GenerateNoteCaption
+    {
+        css::uno::Sequence<OUString> maPropertyNames;  /// import filter 
Caption object formatting property names
+        css::uno::Sequence<css::uno::Any> maPropertyValues; /// import filter 
Caption object formatting property values
+        std::shared_ptr<RichString> mxText;
+
+        OOXGenerateNoteCaption(std::shared_ptr<RichString>& rText)
+            : mxText(rText)
+        {
+        }
+
+        virtual void Generate(SdrCaptionObj& rCaptionObj) override
+        {
+            rtl::Reference<SvxShapeText> 
xAnnoShape(dynamic_cast<SvxShapeText*>(rCaptionObj.getUnoShape().get())); // 
SvxShapeText
+            assert(xAnnoShape && "will not be null");
+
+            if (maPropertyNames.getLength())
+            {
+                // setting a property triggers expensive process, so set them 
all at once
+                
static_cast<SvxShape*>(xAnnoShape.get())->setPropertyValues(maPropertyNames, 
maPropertyValues);
+            }
+
+            // insert text and convert text formatting
+            Reference< XText > xAnnoText( xAnnoShape );
+            xAnnoShape->addActionLock();
+            mxText->convert( xAnnoText );
+            xAnnoShape->removeActionLock();
+        }
+
+        virtual OUString GetSimpleText() const override
+        {
+            return mxText->getStringContent();
+        }
+    };
+}
+
 void Comment::finalizeImport()
 {
     // BIFF12 stores cell range instead of cell address, use first cell of 
this range
@@ -160,24 +198,22 @@ void Comment::finalizeImport()
         ScTableSheetObj* pAnnosSupp = 
static_cast<ScTableSheetObj*>(getSheet().get());
         rtl::Reference<ScAnnotationsObj> xAnnos = 
static_cast<ScAnnotationsObj*>(pAnnosSupp->getAnnotations().get());
         ScDocShell* pDocShell = xAnnos->GetDocShell();
-        // non-empty string required by note implementation (real text will be 
added below)
-        ScPostIt* pPostIt = pDocShell->GetDocFunc().ImportNote( 
maModel.maRange.aStart, OUString( ' ' ) );
-        SdrCaptionObj* pCaption = pPostIt->GetOrCreateCaption( 
maModel.maRange.aStart );
 
-        rtl::Reference< SvxShapeText > xAnnoShape( 
dynamic_cast<SvxShapeText*>(pCaption->getUnoShape().get() ) ); // SvxShapeText
-        assert(xAnnoShape && "will not be null");
-        // setting a property triggers expensive process, so set them all at 
once
+        auto xGenerator = 
std::make_unique<OOXGenerateNoteCaption>(maModel.mxText);
 
         // Add shape formatting properties (autoFill, colHidden and rowHidden 
are dropped)
         // vvv TODO vvv TextFitToSize should be a drawing::TextFitToSizeType 
not bool
-        Sequence<OUString> aPropertyNames{ "TextFitToSize", "MoveProtect", 
"TextHorizontalAdjust", "TextVerticalAdjust" };
-        Sequence<Any> aPropertyValues{ Any(maModel.mbAutoScale), 
Any(maModel.mbLocked),
-                Any(lcl_ToHorizAlign( maModel.mnTHA )), Any(lcl_ToVertAlign( 
maModel.mnTVA )) };
+        xGenerator->maPropertyNames =
+            css::uno::Sequence<OUString>{ "TextFitToSize", "MoveProtect", 
"TextHorizontalAdjust", "TextVerticalAdjust" };
+        xGenerator->maPropertyValues =
+            css::uno::Sequence<css::uno::Any>{ Any(maModel.mbAutoScale), 
Any(maModel.mbLocked),
+                                               Any(lcl_ToHorizAlign( 
maModel.mnTHA )), Any(lcl_ToVertAlign( maModel.mnTVA )) };
 
+        tools::Rectangle aCaptionRect;
         if( maModel.maAnchor.Width > 0 && maModel.maAnchor.Height > 0 )
         {
-            xAnnoShape->setPosition( css::awt::Point( maModel.maAnchor.X, 
maModel.maAnchor.Y ) );
-            xAnnoShape->setSize( css::awt::Size( maModel.maAnchor.Width, 
maModel.maAnchor.Height ) );
+            aCaptionRect = tools::Rectangle(Point(maModel.maAnchor.X, 
maModel.maAnchor.Y),
+                                            Size(maModel.maAnchor.Width, 
maModel.maAnchor.Height));
         }
 
         // convert shape formatting and visibility
@@ -188,8 +224,8 @@ void Comment::finalizeImport()
             css::awt::Rectangle aShapeRect = 
pVmlNoteShape->getShapeRectangle();
             if (aShapeRect.Width > 0 || aShapeRect.Height > 0)
             {
-                xAnnoShape->setPosition(css::awt::Point(aShapeRect.X, 
aShapeRect.Y));
-                xAnnoShape->setSize(css::awt::Size(aShapeRect.Width, 
aShapeRect.Height));
+                aCaptionRect = tools::Rectangle(Point(aShapeRect.X, 
aShapeRect.Y),
+                                                Size(aShapeRect.Width, 
aShapeRect.Height));
 
                 ::oox::drawingml::ShapePropertyMap 
aPropMap(pVmlNoteShape->makeShapePropertyMap());
 
@@ -197,12 +233,12 @@ void Comment::finalizeImport()
                 Sequence<Any> aVMLPropValues;
                 aPropMap.fillSequences(aVMLPropNames, aVMLPropValues);
 
-                sal_uInt32 nOldPropLen = aPropertyNames.getLength();
+                sal_uInt32 nOldPropLen = 
xGenerator->maPropertyNames.getLength();
                 sal_uInt32 nVMLPropLen = aVMLPropNames.getLength();
-                aPropertyNames.realloc(nOldPropLen + nVMLPropLen);
-                aPropertyValues.realloc(nOldPropLen + nVMLPropLen);
-                OUString* pNames = aPropertyNames.getArray();
-                Any* pValues = aPropertyValues.getArray();
+                xGenerator->maPropertyNames.realloc(nOldPropLen + nVMLPropLen);
+                xGenerator->maPropertyValues.realloc(nOldPropLen + 
nVMLPropLen);
+                OUString* pNames = xGenerator->maPropertyNames.getArray();
+                Any* pValues = xGenerator->maPropertyValues.getArray();
                 for (sal_uInt32 i = 0; i < nVMLPropLen; ++i)
                 {
                     pNames[nOldPropLen + i] = aVMLPropNames[i];
@@ -215,28 +251,24 @@ void Comment::finalizeImport()
 
             // Setting comment text alignment
             const ::oox::vml::ClientData* xClientData = 
pVmlNoteShape->getClientData();
-            sal_uInt32 nOldPropLen = aPropertyNames.getLength();
-            aPropertyNames.realloc(nOldPropLen + 2);
-            aPropertyValues.realloc(nOldPropLen + 2);
-            OUString* pNames = aPropertyNames.getArray();
-            Any* pValues = aPropertyValues.getArray();
+            sal_uInt32 nOldPropLen = xGenerator->maPropertyNames.getLength();
+            xGenerator->maPropertyNames.realloc(nOldPropLen + 2);
+            xGenerator->maPropertyValues.realloc(nOldPropLen + 2);
+            OUString* pNames = xGenerator->maPropertyNames.getArray();
+            Any* pValues = xGenerator->maPropertyValues.getArray();
             pNames[nOldPropLen] = "TextVerticalAdjust";
             pValues[nOldPropLen] <<= 
lcl_ToVertAlign(xClientData->mnTextVAlign);
             pNames[nOldPropLen + 1] = "ParaAdjust";
             pValues[nOldPropLen + 1] <<= lcl_ToParaAlign( 
xClientData->mnTextHAlign);
         }
 
-        
static_cast<SvxShape*>(xAnnoShape.get())->setPropertyValues(aPropertyNames, 
aPropertyValues);
+        xGenerator->mxText->finalizeImport(*this);
+
+        pDocShell->GetDocFunc().ImportNote(maModel.maRange.aStart, 
std::move(xGenerator),
+                                           aCaptionRect, bVisible);
 
         if (bVisible)
             pDocShell->GetDocFunc().ShowNote( maModel.maRange.aStart, bVisible 
);
-
-        // insert text and convert text formatting
-        maModel.mxText->finalizeImport(*this);
-        Reference< XText > xAnnoText( xAnnoShape );
-        xAnnoShape->addActionLock();
-        maModel.mxText->convert( xAnnoText );
-        xAnnoShape->removeActionLock();
     }
     catch( Exception& )
     {
diff --git a/sc/source/filter/oox/richstring.cxx 
b/sc/source/filter/oox/richstring.cxx
index a1345179c19a..06db87e3c733 100644
--- a/sc/source/filter/oox/richstring.cxx
+++ b/sc/source/filter/oox/richstring.cxx
@@ -398,18 +398,24 @@ void RichString::convert( const Reference< XText >& 
rxText )
     }
 }
 
-std::unique_ptr<EditTextObject> RichString::convert( ScEditEngineDefaulter& 
rEE, const oox::xls::Font* pFirstPortionFont )
+OUString RichString::getStringContent() const
 {
-    ESelection aSelection;
-
     OUStringBuffer sString;
     for( auto& rTextPortion : maTextPortions )
         sString.append(rTextPortion.getText());
+    return sString.makeStringAndClear();
+}
+
+std::unique_ptr<EditTextObject> RichString::convert( ScEditEngineDefaulter& 
rEE, const oox::xls::Font* pFirstPortionFont )
+{
+    ESelection aSelection;
+
+    OUString sString(getStringContent());
 
     // fdo#84370 - diving into editeng is not thread safe.
     SolarMutexGuard aGuard;
 
-    rEE.SetTextCurrentDefaults( sString.makeStringAndClear() );
+    rEE.SetTextCurrentDefaults(sString);
 
     for( auto& rTextPortion : maTextPortions )
     {
diff --git a/sc/source/ui/docshell/docfunc.cxx 
b/sc/source/ui/docshell/docfunc.cxx
index 4d3288558c40..e89e48476e1c 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -1405,7 +1405,9 @@ void ScDocFunc::ReplaceNote( const ScAddress& rPos, const 
OUString& rNoteText, c
     }
 }
 
-ScPostIt* ScDocFunc::ImportNote( const ScAddress& rPos, const OUString& 
rNoteText  )
+void ScDocFunc::ImportNote( const ScAddress& rPos,
+                            std::unique_ptr<GenerateNoteCaption> xGenerator,
+                            const tools::Rectangle& rCaptionRect, bool bShown )
 {
     ScDocShellModificator aModificator( rDocShell );
     ScDocument& rDoc = rDocShell.GetDocument();
@@ -1414,13 +1416,12 @@ ScPostIt* ScDocFunc::ImportNote( const ScAddress& rPos, 
const OUString& rNoteTex
     SAL_WARN_IF(pOldNote, "sc.ui", "imported data has >1 notes on same cell? 
at pos " << rPos);
 
     // create new note
-    ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, 
rNoteText, false, true, /*nNoteId*/0 );
+    ScNoteUtil::CreateNoteFromGenerator(rDoc, rPos, std::move(xGenerator),
+                                        rCaptionRect, bShown);
 
     rDoc.SetStreamValid(rPos.Tab(), false);
 
     aModificator.SetDocumentModified();
-
-    return pNewNote;
 }
 
 bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& 
rPattern,
diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx
index 77bdb57012de..6419e285d5b7 100644
--- a/sc/source/ui/inc/docfunc.hxx
+++ b/sc/source/ui/inc/docfunc.hxx
@@ -29,6 +29,7 @@
 #include <vector>
 #include <map>
 
+class GenerateNoteCaption;
 class ScEditEngineDefaulter;
 class SdrUndoAction;
 class ScAddress;
@@ -47,7 +48,6 @@ class ScConditionalFormat;
 class ScConditionalFormatList;
 class ScUndoRemoveMerge;
 class ScRangeName;
-class ScPostIt;
 
 enum class TransliterationFlags;
 enum class CreateNameFlags;
@@ -58,6 +58,10 @@ namespace sc
     class SparklineGroup;
     class Sparkline;
 }
+namespace tools
+{
+    class Rectangle;
+}
 
 class ScDocFunc
 {
@@ -124,7 +128,9 @@ public:
 
     void            SetNoteText( const ScAddress& rPos, const OUString& 
rNoteText, bool bApi );
     void            ReplaceNote( const ScAddress& rPos, const OUString& 
rNoteText, const OUString* pAuthor, const OUString* pDate, bool bApi );
-    SC_DLLPUBLIC ScPostIt* ImportNote( const ScAddress& rPos, const OUString& 
rNoteText );
+    SC_DLLPUBLIC void ImportNote( const ScAddress& rPos,
+                                  std::unique_ptr<GenerateNoteCaption> 
xGenerator,
+                                  const tools::Rectangle& rCaptionRect, bool 
bShown );
 
     bool            ApplyAttributes( const ScMarkData& rMark, const 
ScPatternAttr& rPattern,
                                            bool bApi );

Reply via email to