[Libreoffice-commits] core.git: Branch 'feature/calc-coordinates' - 53 commits - chart2/qa chart2/source chart2/workbench codemaker/source compilerplugins/clang config_host/config_skia.h.in configmgr/qa configmgr/source configure.ac connectivity/source cui/source cui/uiconfig desktop/source download.lst editeng/source external/skia include/comphelper include/editeng include/LibreOfficeKit include/toolkit include/unotools include/vcl libreofficekit/source Makefile.in officecfg/registry oox/source package/source schema/libreoffice schema/odf1.3 sc/inc sc/qa sc/source sfx2/source stoc/test svx/Library_svx.mk svx/source svx/uiconfig svx/UIConfig_svx.mk sw/inc sw/qa sw/source testtools/source toolkit/inc toolkit/source uitest/ui_logger_dsl unotools/source uui/source vcl/source vcl/unx writerfilter/source xmlsecurity/qa xmlsecurity/source

Dennis Francis (via logerrit) logerrit at kemper.freedesktop.org
Sun May 24 19:14:30 UTC 2020


Rebased ref, commits from common ancestor:
commit e7546301e8569847b9236bd859792079e97e0c50
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sun May 24 22:40:51 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:40:01 2020 +0530

    lokit: scPrintTwipsMsgs: LOK_CALLBACK_CELL_VIEW_CURSOR
    
    Allow print twips coordinates in LOK_CALLBACK_CELL_VIEW_CURSOR
    
    Change-Id: I0373cbd2b87b4d1088af41453ab548274de6ca23

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index b1da568c3128..405dd5e7de1a 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -5754,8 +5754,13 @@ void ScGridWindow::notifyKitCellViewCursor(const SfxViewShell* pForShell) const
         assert(pForTabView);
         if (!pForTabView)
             return;
-        aCursor = pForTabView->GetViewData().describeCellCursorAt(
-            pViewData->GetCurX(), pViewData->GetCurY()); // our position.
+
+        if (comphelper::LibreOfficeKit::isCompatFlagSet(
+            comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+            aCursor = pViewData->describeCellCursorInPrintTwips();
+        else
+            aCursor = pForTabView->GetViewData().describeCellCursorAt(
+                pViewData->GetCurX(), pViewData->GetCurY()); // our position.
     }
     SfxLokHelper::notifyOtherView(pViewShell, pForShell, LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", aCursor);
 }
@@ -5765,9 +5770,33 @@ void ScGridWindow::notifyKitCellViewCursor(const SfxViewShell* pForShell) const
 // event, and others a cell_view_cursor event.
 //
 // NB. we need to re-construct the cursor details for each other view in their
-// own zoomed co-ordinate system.
+// own zoomed co-ordinate system (but not in scPrintTwipsMsgs mode).
 void ScGridWindow::updateKitCellCursor(const SfxViewShell* pForShell) const
 {
+    if (comphelper::LibreOfficeKit::isCompatFlagSet(
+            comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+    {
+        ScTabViewShell* pViewShell = pViewData->GetViewShell();
+        // Generate the cursor info string just once and directly send to all.
+        // Calling notifyKitCellViewCursor() would regenerate the
+        // cursor-string unnecessarily.
+        OString aCursor = getCellCursor();
+
+        if (pForShell)
+        {
+            SfxLokHelper::notifyOtherView(pViewShell, pForShell,
+                    LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", aCursor);
+        }
+        else
+        {
+            notifyKitCellCursor();
+            SfxLokHelper::notifyOtherViews(pViewShell,
+                    LOK_CALLBACK_CELL_VIEW_CURSOR, "rectangle", aCursor);
+        }
+
+        return;
+    }
+
     if (!pForShell)
     {
         for (SfxViewShell* it = SfxViewShell::GetFirst(); it;
commit 07cb2b5b8ab7624868e19e0aa687d36195400fd7
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sun May 24 20:31:52 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:40:01 2020 +0530

    lokit: scPrintTwipsMsgs: LOK_CALLBACK_REFERENCE_MARKS
    
    Allow print twips coordinates in LOK_CALLBACK_REFERENCE_MARKS
    
    Change-Id: I1bf84c5aebe84ee034ac27932fa8a01d0a3ae831

diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 83079851a552..6f66e14e9b68 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -434,6 +434,25 @@ ReferenceMark ScInputHandler::GetReferenceMark( ScViewData& rViewData, ScDocShel
 {
     ScSplitPos eWhich = rViewData.GetActivePart();
 
+    // This method is LOK specific.
+    if (comphelper::LibreOfficeKit::isCompatFlagSet(
+            comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+    {
+        SCCOL nCol1 = nX1, nCol2 = nX2;
+        SCROW nRow1 = nY1, nRow2 = nY2;
+        PutInOrder(nCol1, nCol2);
+        PutInOrder(nRow1, nRow2);
+        if (nCol1 == nCol2 && nRow1 == nRow2)
+            pDocSh->GetDocument().ExtendMerge(nCol1, nRow1, nCol2, nRow2, nTab);
+
+        Point aTopLeft = rViewData.GetPrintTwipsPos(nCol1, nRow1);
+        Point aBottomRight = rViewData.GetPrintTwipsPos(nCol2 + 1, nRow2 + 1);
+        long nSizeX = aBottomRight.X() - aTopLeft.X() - 1;
+        long nSizeY = aBottomRight.Y() - aTopLeft.Y() - 1;
+
+        return ReferenceMark(aTopLeft.X(), aTopLeft.Y(), nSizeX, nSizeY, nTab, rColor);
+    }
+
     Point aScrPos = rViewData.GetScrPos( nX1, nY1, eWhich );
     long nScrX = aScrPos.X();
     long nScrY = aScrPos.Y();
commit 69a8d8bb6bbeb0e94fe7c4d0314ca937dad52c34
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sun May 24 17:21:59 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:40:00 2020 +0530

    lokit: do not set an artificial cursor size when it is zero...
    
    when we send the message in print twips coordinates. It is important for
    the client to know the exact position and coordinates to allow client
    side print-twips -> tile-twips conversion when/if it is needed.
    
    Change-Id: I6699894758886f1b5648ac9bf3c9e6ab4192c72e

diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index 4079191db11d..6dd308b33fb0 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -2257,15 +2257,13 @@ OString ScViewData::describeCellCursorAt(SCCOL nX, SCROW nY, bool bPixelAligned)
     }
     else
     {
-        // make it a slim cell cursor, but not empty
-        if (nSizeX == 0)
-            nSizeX = TWIPS_PER_PIXEL;
-        if (nSizeY == 0)
-            nSizeY = TWIPS_PER_PIXEL;
-
+        // look at Rectangle( const Point& rLT, const Size& rSize ) for the decrement.
+        if (nSizeX)
+            --nSizeX;
+        if (nSizeY)
+            --nSizeY;
         ss << aCellPos.getX() << ", " << aCellPos.getY()
-            // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
-            << ", " << nSizeX - 1 << ", " << nSizeY - 1 << ", "
+            << ", " << nSizeX << ", " << nSizeY << ", "
             << nX << ", " << nY;
     }
 
commit 6624b551966f47046cac46644427c7271af60a93
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sun May 24 12:50:16 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:59 2020 +0530

    lokit: scPrintTwipsMsgs: LOK_CALLBACK_CELL_CURSOR
    
    Allow print twips coordinates in LOK_CALLBACK_CELL_CURSOR msg.
    
    Change-Id: Ib9de372db46db9d462983e15fb12d58624d066f5

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index e88027b6d754..b1da568c3128 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -5727,6 +5727,10 @@ OString ScGridWindow::getCellCursor() const
     if (!mpOOCursors)
         return "EMPTY";
 
+    if (comphelper::LibreOfficeKit::isCompatFlagSet(
+            comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+        return pViewData->describeCellCursorInPrintTwips();
+
     return pViewData->describeCellCursor();
 }
 
commit 314294b923d55fb6b0b6e2755cf4b13657a04ba2
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sat May 23 12:22:56 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:59 2020 +0530

    Allow cell coordinates calculation in print twips too
    
    Change-Id: Ie8f23bd7ba8de57d7aab104add99501a54f08819

diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx
index 345f9d9ae00f..b893eb63dab0 100644
--- a/sc/source/ui/inc/viewdata.hxx
+++ b/sc/source/ui/inc/viewdata.hxx
@@ -503,6 +503,7 @@ public:
 
                     // TRUE: Cell is merged
     bool            GetMergeSizePixel( SCCOL nX, SCROW nY, long& rSizeXPix, long& rSizeYPix ) const;
+    bool            GetMergeSizePrintTwips( SCCOL nX, SCROW nY, long& rSizeXTwips, long& rSizeYTwips ) const;
     void            GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich,
                                         SCCOL& rPosX, SCROW& rPosY,
                                         bool bTestMerge = true, bool bRepair = false );
@@ -603,10 +604,13 @@ public:
                                 bool bAllowNeg = false ) const;
     Point           GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScHSplitPos eWhich ) const;
     Point           GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScVSplitPos eWhich ) const;
+    /// returns the position (top-left corner) of the requested cell in print twips coordinates.
+    Point           GetPrintTwipsPos( SCCOL nCol, SCROW nRow ) const;
 
     /// return json for our cursor position.
     OString         describeCellCursor() const { return describeCellCursorAt(GetCurX(), GetCurY()); }
-    OString         describeCellCursorAt( SCCOL nCol, SCROW nRow ) const;
+    OString         describeCellCursorInPrintTwips() const { return describeCellCursorAt(GetCurX(), GetCurY(), false); }
+    OString         describeCellCursorAt( SCCOL nCol, SCROW nRow, bool bPixelAligned = true ) const;
 
     SCCOL           CellsAtX( SCCOL nPosX, SCCOL nDir, ScHSplitPos eWhichX, sal_uInt16 nScrSizeY = SC_SIZE_NONE ) const;
     SCROW           CellsAtY( SCROW nPosY, SCROW nDir, ScVSplitPos eWhichY, sal_uInt16 nScrSizeX = SC_SIZE_NONE ) const;
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index 0fddf7862b82..4079191db11d 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -2208,33 +2208,66 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich,
     return Point( nScrPosX, nScrPosY );
 }
 
-OString ScViewData::describeCellCursorAt(SCCOL nX, SCROW nY) const
+Point ScViewData::GetPrintTwipsPos(SCCOL nCol, SCROW nRow) const
 {
-    Point aScrPos = GetScrPos( nX, nY, SC_SPLIT_BOTTOMRIGHT, true );
+    // hidden ones are given 0 sizes by these by default.
+    // TODO: rewrite this to loop over spans (matters for jumbosheets).
+    long nPosX = nCol ? pDoc->GetColWidth(0, nCol - 1, nTabNo) : 0;
+    // This is now fast as it loops over spans.
+    long nPosY = nRow ? pDoc->GetRowHeight(0, nRow - 1, nTabNo) : 0;
+    // TODO: adjust for RTL layout case.
 
-    long nSizeXPix;
-    long nSizeYPix;
-    GetMergeSizePixel( nX, nY, nSizeXPix, nSizeYPix );
+    return Point(nPosX, nPosY);
+}
+
+OString ScViewData::describeCellCursorAt(SCCOL nX, SCROW nY, bool bPixelAligned) const
+{
+    const bool bPosSizeInPixels = bPixelAligned;
+    Point aCellPos = bPosSizeInPixels ? GetScrPos( nX, nY, SC_SPLIT_BOTTOMRIGHT, true ) :
+            GetPrintTwipsPos(nX, nY);
+
+    long nSizeX;
+    long nSizeY;
+    if (bPosSizeInPixels)
+        GetMergeSizePixel( nX, nY, nSizeX, nSizeY );
+    else
+        GetMergeSizePrintTwips(nX, nY, nSizeX, nSizeY);
 
-    double fPPTX = GetPPTX();
-    double fPPTY = GetPPTY();
+    std::stringstream ss;
+    if (bPosSizeInPixels)
+    {
+        double fPPTX = GetPPTX();
+        double fPPTY = GetPPTY();
 
-    // make it a slim cell cursor, but not empty
-    if (nSizeXPix == 0)
-        nSizeXPix = 1;
+        // make it a slim cell cursor, but not empty
+        if (nSizeX == 0)
+            nSizeX = 1;
 
-    if (nSizeYPix == 0)
-        nSizeYPix = 1;
+        if (nSizeY == 0)
+            nSizeY = 1;
 
-    long nPosXTw = rtl::math::round(aScrPos.getX() / fPPTX);
-    long nPosYTw = rtl::math::round(aScrPos.getY() / fPPTY);
-    // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
-    long nSizeXTw = rtl::math::round(nSizeXPix / fPPTX) - 1;
-    long nSizeYTw = rtl::math::round(nSizeYPix / fPPTY) - 1;
+        long nPosXTw = rtl::math::round(aCellPos.getX() / fPPTX);
+        long nPosYTw = rtl::math::round(aCellPos.getY() / fPPTY);
+        // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
+        long nSizeXTw = rtl::math::round(nSizeX / fPPTX) - 1;
+        long nSizeYTw = rtl::math::round(nSizeY / fPPTY) - 1;
 
-    std::stringstream ss;
-    ss << nPosXTw << ", " << nPosYTw << ", " << nSizeXTw << ", " << nSizeYTw << ", "
-       << nX << ", " << nY;
+        ss << nPosXTw << ", " << nPosYTw << ", " << nSizeXTw << ", " << nSizeYTw << ", "
+            << nX << ", " << nY;
+    }
+    else
+    {
+        // make it a slim cell cursor, but not empty
+        if (nSizeX == 0)
+            nSizeX = TWIPS_PER_PIXEL;
+        if (nSizeY == 0)
+            nSizeY = TWIPS_PER_PIXEL;
+
+        ss << aCellPos.getX() << ", " << aCellPos.getY()
+            // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
+            << ", " << nSizeX - 1 << ", " << nSizeY - 1 << ", "
+            << nX << ", " << nY;
+    }
 
     return ss.str().c_str();
 }
@@ -2375,6 +2408,22 @@ bool ScViewData::GetMergeSizePixel( SCCOL nX, SCROW nY, long& rSizeXPix, long& r
     }
 }
 
+bool ScViewData::GetMergeSizePrintTwips(SCCOL nX, SCROW nY, long& rSizeXTwips, long& rSizeYTwips) const
+{
+    const ScMergeAttr* pMerge = pDoc->GetAttr(nX, nY, nTabNo, ATTR_MERGE);
+    SCCOL nCountX = pMerge->GetColMerge();
+    if (!nCountX)
+        nCountX = 1;
+    rSizeXTwips = pDoc->GetColWidth(nX, nX + nCountX - 1, nTabNo);
+
+    SCROW nCountY = pMerge->GetRowMerge();
+    if (!nCountY)
+        nCountY = 1;
+    rSizeYTwips = pDoc->GetRowHeight(nY, nY + nCountY - 1, nTabNo);
+
+    return (nCountX > 1 || nCountY > 1);
+}
+
 void ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich,
                                         SCCOL& rPosX, SCROW& rPosY,
                                         bool bTestMerge, bool bRepair )
commit 5ce3e57ba43a45c31b4c8c210b95894fdcdfe42f
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sat May 23 11:00:19 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:58 2020 +0530

    use lcl_ExtendTiledDimension() in getRowColumnHeaders()
    
    to avoid code repetitions.
    
    Change-Id: If83b42175fb53132174fa33d169806e17a4a5cbe

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 7c0bfa847aba..31119a239bf9 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2669,45 +2669,7 @@ OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
 
     /// 2) if we are approaching current max tiled row, signal a size changed event
     ///    and invalidate the involved area
-
-    if (nEndRow > aViewData.GetMaxTiledRow() - nVisibleRows)
-    {
-        ScDocShell* pDocSh = aViewData.GetDocShell();
-        ScModelObj* pModelObj = pDocSh ? comphelper::getUnoTunnelImplementation<ScModelObj>( pDocSh->GetModel() ) : nullptr;
-        Size aOldSize(0, 0);
-        if (pModelObj)
-            aOldSize = pModelObj->getDocumentSize();
-
-        aViewData.SetMaxTiledRow(std::min(std::max(nEndRow, aViewData.GetMaxTiledRow()) + nVisibleRows, long(MAXTILEDROW)));
-
-        Size aNewSize(0, 0);
-        if (pModelObj)
-            aNewSize = pModelObj->getDocumentSize();
-
-        SAL_INFO("sc.lok.header", "Row Header: a new height: " << aNewSize.Height());
-        if (pDocSh)
-        {
-            // New area extended to the bottom of the sheet after last row
-            // excluding overlapping area with aNewColArea
-            tools::Rectangle aNewRowArea(0, aOldSize.getHeight(), aOldSize.getWidth(), aNewSize.getHeight());
-
-            // Only invalidate if spreadsheet extended to the bottom
-            if (aNewRowArea.getHeight())
-            {
-                UpdateSelectionOverlay();
-                SfxLokHelper::notifyInvalidation(aViewData.GetViewShell(), aNewRowArea.toString());
-            }
-
-            // Provide size in the payload, so clients don't have to
-            // call lok::Document::getDocumentSize().
-            std::stringstream ss;
-            ss << aNewSize.Width() << ", " << aNewSize.Height();
-            OString sSize = ss.str().c_str();
-            ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(aViewData.GetViewShell()->GetCurrentDocument());
-            SfxLokHelper::notifyDocumentSizeChanged(aViewData.GetViewShell(), sSize, pModel, false);
-        }
-    }
-
+    lcl_ExtendTiledDimension(/* bColumn */ false, nEndRow, nVisibleRows, *this, aViewData);
 
     /// 3) create string data for rows
 
@@ -2803,46 +2765,7 @@ OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
 
     /// 2) if we are approaching current max tiled column, signal a size changed event
     ///    and invalidate the involved area
-
-    if (nEndCol > aViewData.GetMaxTiledCol() - nVisibleCols)
-    {
-        ScDocShell* pDocSh = aViewData.GetDocShell();
-        ScModelObj* pModelObj = pDocSh ? comphelper::getUnoTunnelImplementation<ScModelObj>( pDocSh->GetModel() ) : nullptr;
-        Size aOldSize(0, 0);
-        if (pModelObj)
-            aOldSize = pModelObj->getDocumentSize();
-
-        aViewData.SetMaxTiledCol(std::min(std::max(nEndCol, aViewData.GetMaxTiledCol()) + nVisibleCols, long(pDoc->MaxCol())));
-
-        Size aNewSize(0, 0);
-        if (pModelObj)
-            aNewSize = pModelObj->getDocumentSize();
-
-        if (pDocSh)
-        {
-            // New area extended to the right of the sheet after last column
-            // including overlapping area with aNewRowArea
-            tools::Rectangle aNewColArea(aOldSize.getWidth(), 0, aNewSize.getWidth(), aNewSize.getHeight());
-
-            // Only invalidate if spreadsheet extended to the bottom
-            if (aNewColArea.getWidth())
-            {
-                UpdateSelectionOverlay();
-                SfxLokHelper::notifyInvalidation(aViewData.GetViewShell(), aNewColArea.toString());
-            }
-
-            if (aOldSize != aNewSize)
-            {
-                // Provide size in the payload, so clients don't have to
-                // call lok::Document::getDocumentSize().
-                std::stringstream ss;
-                ss << aNewSize.Width() << ", " << aNewSize.Height();
-                OString sSize = ss.str().c_str();
-                ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(aViewData.GetViewShell()->GetCurrentDocument());
-                SfxLokHelper::notifyDocumentSizeChanged(aViewData.GetViewShell(), sSize, pModel, false);
-            }
-        }
-    }
+    lcl_ExtendTiledDimension(/* bColumn */ true, nEndCol, nVisibleCols, *this, aViewData);
 
     /// 3) create string data for columns
 
commit ab9a53c4dff622c9ed747cc82c03f67a67f33aed
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sat May 23 10:47:10 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:58 2020 +0530

    use helper-class ScRangeProvider in getRowColumnHeader()
    
    and avoid some code repetitions.
    
    Change-Id: I3e006bc8d9880f3e1ec892aa8f2423edbf9bbf14

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index f0d272ca7895..7c0bfa847aba 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2621,6 +2621,10 @@ OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
             mnLOKStartHeaderCol + 1, mnLOKStartHeaderRow + 1,
             mnLOKEndHeaderCol, mnLOKEndHeaderRow);
 
+    ScRangeProvider aRangeProvider(rRectangle, /* bInPixels */ false, aViewData,
+                                   /* nEnlargeX */ 2, /* nEnlargeY */ 2);
+    const ScRange& rCellRange = aRangeProvider.getCellRange();
+
     /// *** start collecting ROWS ***
 
     /// 1) compute start and end rows
@@ -2629,17 +2633,9 @@ OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
     {
         SAL_INFO("sc.lok.header", "Row Header: compute start/end rows.");
         long nEndHeightPx = 0;
-        long nRectTopPx = rRectangle.Top() * aViewData.GetPPTX();
-        long nRectBottomPx = rRectangle.Bottom() * aViewData.GetPPTY();
-
-        const auto& rTopNearest = aViewData.GetLOKHeightHelper().getNearestByPosition(nRectTopPx);
-        const auto& rBottomNearest = aViewData.GetLOKHeightHelper().getNearestByPosition(nRectBottomPx);
-
-        ScBoundsProvider aBoundingRowsProvider(aViewData, nTab, /*bColumnHeader: */ false);
-        aBoundingRowsProvider.Compute(rTopNearest, rBottomNearest, nRectTopPx, nRectBottomPx);
-        aBoundingRowsProvider.EnlargeBy(2);
-        aBoundingRowsProvider.GetStartIndexAndPosition(nStartRow, nStartHeightPx);
-        aBoundingRowsProvider.GetEndIndexAndPosition(nEndRow, nEndHeightPx);
+        nStartRow = rCellRange.aStart.Row();
+        nEndRow = rCellRange.aEnd.Row();
+        aRangeProvider.getRowPositions(nStartHeightPx, nEndHeightPx);
 
         aViewData.GetLOKHeightHelper().removeByIndex(mnLOKStartHeaderRow);
         aViewData.GetLOKHeightHelper().removeByIndex(mnLOKEndHeaderRow);
@@ -2772,17 +2768,9 @@ OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
     {
         SAL_INFO("sc.lok.header", "Column Header: compute start/end columns.");
         long nEndWidthPx = 0;
-        long nRectLeftPx = rRectangle.Left() * aViewData.GetPPTX();
-        long nRectRightPx = rRectangle.Right() * aViewData.GetPPTY();
-
-        const auto& rLeftNearest = aViewData.GetLOKWidthHelper().getNearestByPosition(nRectLeftPx);
-        const auto& rRightNearest = aViewData.GetLOKWidthHelper().getNearestByPosition(nRectRightPx);
-
-        ScBoundsProvider aBoundingColsProvider(aViewData, nTab, /*bColumnHeader: */ true);
-        aBoundingColsProvider.Compute(rLeftNearest, rRightNearest, nRectLeftPx, nRectRightPx);
-        aBoundingColsProvider.EnlargeBy(2);
-        aBoundingColsProvider.GetStartIndexAndPosition(nStartCol, nStartWidthPx);
-        aBoundingColsProvider.GetEndIndexAndPosition(nEndCol, nEndWidthPx);
+        nStartCol = rCellRange.aStart.Col();
+        nEndCol = rCellRange.aEnd.Col();
+        aRangeProvider.getColPositions(nStartWidthPx, nEndWidthPx);
 
         aViewData.GetLOKWidthHelper().removeByIndex(mnLOKStartHeaderCol);
         aViewData.GetLOKWidthHelper().removeByIndex(mnLOKEndHeaderCol);
commit 9947021efa2481dcda99f987013ea8a0de786536
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Sat May 23 10:25:11 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:57 2020 +0530

    lokit: move helper classes/functions to anonymous namespace
    
    and drop static keyword from the local functions. No functional changes
    involved, just a pure refactor to aid an upcoming cleanup of
    getRowColumnHeaders() method.
    
    Change-Id: I7daafdc8f644f73d10d594cb7e0f5b25e6464ca5

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index c051547b08c0..f0d272ca7895 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2432,6 +2432,167 @@ void lcl_createGroupsData(
     }
 }
 
+class ScRangeProvider
+{
+public:
+    ScRangeProvider(const tools::Rectangle& rArea, bool bInPixels,
+                    ScViewData& rViewData, SCCOLROW nEnlargeX = 0,
+                    SCCOLROW nEnlargeY = 0):
+        mrViewData(rViewData),
+        mnEnlargeX(nEnlargeX),
+        mnEnlargeY(nEnlargeY)
+    {
+        tools::Rectangle aAreaPx = bInPixels ? rArea :
+            tools::Rectangle(rArea.Left() * mrViewData.GetPPTX(),
+                             rArea.Top() * mrViewData.GetPPTY(),
+                             rArea.Right() * mrViewData.GetPPTX(),
+                             rArea.Bottom() * mrViewData.GetPPTY());
+        calculateBounds(aAreaPx);
+    }
+
+    const ScRange& getCellRange() const
+    {
+        return maRange;
+    }
+
+    void getColPositions(long& rStartColPos, long& rEndColPos) const
+    {
+        rStartColPos = maBoundPositions.Left();
+        rEndColPos = maBoundPositions.Right();
+    }
+
+    void getRowPositions(long& rStartRowPos, long& rEndRowPos) const
+    {
+        rStartRowPos = maBoundPositions.Top();
+        rEndRowPos = maBoundPositions.Bottom();
+    }
+
+private:
+    void calculateBounds(const tools::Rectangle& rAreaPx)
+    {
+        long nLeftPx = 0, nRightPx = 0;
+        SCCOLROW nStartCol = -1, nEndCol = -1;
+        calculateDimensionBounds(rAreaPx.Left(), rAreaPx.Right(), true,
+                                 nStartCol, nEndCol, nLeftPx, nRightPx,
+                                 mnEnlargeX, mrViewData);
+        long nTopPx = 0, nBottomPx = 0;
+        SCCOLROW nStartRow = -1, nEndRow = -1;
+        calculateDimensionBounds(rAreaPx.Top(), rAreaPx.Bottom(), false,
+                                 nStartRow, nEndRow, nTopPx, nBottomPx,
+                                 mnEnlargeY, mrViewData);
+
+        maRange.aStart.Set(nStartCol, nStartRow, mrViewData.GetTabNo());
+        maRange.aEnd.Set(nEndCol, nEndRow, mrViewData.GetTabNo());
+
+        maBoundPositions.SetLeft(nLeftPx);
+        maBoundPositions.SetRight(nRightPx);
+        maBoundPositions.SetTop(nTopPx);
+        maBoundPositions.SetBottom(nBottomPx);
+    }
+
+    // All positions are in pixels.
+    static void calculateDimensionBounds(const long nStartPos, const long nEndPos,
+                                         bool bColumns, SCCOLROW& rStartIndex,
+                                         SCCOLROW& rEndIndex, long& rBoundStart,
+                                         long& rBoundEnd, SCCOLROW nEnlarge,
+                                         ScViewData& rViewData)
+    {
+        ScPositionHelper& rPosHelper = bColumns ? rViewData.GetLOKWidthHelper() :
+            rViewData.GetLOKHeightHelper();
+        const auto& rStartNearest = rPosHelper.getNearestByPosition(nStartPos);
+        const auto& rEndNearest = rPosHelper.getNearestByPosition(nEndPos);
+
+        ScBoundsProvider aBoundsProvider(rViewData, rViewData.GetTabNo(), bColumns);
+        aBoundsProvider.Compute(rStartNearest, rEndNearest, nStartPos, nEndPos);
+        aBoundsProvider.EnlargeBy(nEnlarge);
+        if (bColumns)
+        {
+            SCCOL nStartCol = -1, nEndCol = -1;
+            aBoundsProvider.GetStartIndexAndPosition(nStartCol, rBoundStart);
+            aBoundsProvider.GetEndIndexAndPosition(nEndCol, rBoundEnd);
+            rStartIndex = nStartCol;
+            rEndIndex = nEndCol;
+        }
+        else
+        {
+            SCROW nStartRow = -1, nEndRow = -1;
+            aBoundsProvider.GetStartIndexAndPosition(nStartRow, rBoundStart);
+            aBoundsProvider.GetEndIndexAndPosition(nEndRow, rBoundEnd);
+            rStartIndex = nStartRow;
+            rEndIndex = nEndRow;
+        }
+    }
+
+private:
+
+    ScRange maRange;
+    tools::Rectangle maBoundPositions;
+    ScViewData& mrViewData;
+    SCCOLROW mnEnlargeX;
+    SCCOLROW mnEnlargeY;
+};
+
+void lcl_ExtendTiledDimension(bool bColumn, const SCCOLROW nEnd, const SCCOLROW nExtra,
+                              ScTabView& rTabView, ScViewData& rViewData)
+{
+    ScDocument* pDoc = rViewData.GetDocument();
+    // If we are approaching current max tiled row/col, signal a size changed event
+    // and invalidate the involved area
+    SCCOLROW nMaxTiledIndex = bColumn ? rViewData.GetMaxTiledCol() : rViewData.GetMaxTiledRow();
+    SCCOLROW nHardLimit = !bColumn ? MAXTILEDROW : pDoc ? pDoc->MaxCol() : MAXCOL;
+
+    if (nMaxTiledIndex >= nHardLimit)
+        return;
+
+    if (nEnd <= nMaxTiledIndex - nExtra) // No need to extend.
+        return;
+
+    ScDocShell* pDocSh = rViewData.GetDocShell();
+    ScModelObj* pModelObj = pDocSh ?
+        comphelper::getUnoTunnelImplementation<ScModelObj>( pDocSh->GetModel() ) : nullptr;
+    Size aOldSize(0, 0);
+    if (pModelObj)
+        aOldSize = pModelObj->getDocumentSize();
+
+    SCCOLROW nNewMaxTiledIndex = std::min(std::max(nEnd, nMaxTiledIndex) + nExtra, nHardLimit);
+
+    if (bColumn)
+        rViewData.SetMaxTiledCol(nNewMaxTiledIndex);
+    else
+        rViewData.SetMaxTiledRow(nNewMaxTiledIndex);
+
+    Size aNewSize(0, 0);
+    if (pModelObj)
+        aNewSize = pModelObj->getDocumentSize();
+
+    if (aOldSize == aNewSize)
+        return;
+
+    if (!pDocSh)
+        return;
+
+    // New area extended to the right/bottom of the sheet after last col/row
+    // excluding overlapping area with aNewArea
+    tools::Rectangle aNewArea = bColumn ?
+        tools::Rectangle(aOldSize.getWidth(), 0, aNewSize.getWidth(), aNewSize.getHeight()):
+        tools::Rectangle(0, aOldSize.getHeight(), aNewSize.getWidth(), aNewSize.getHeight());
+
+    // Only invalidate if spreadsheet has extended to the right or bottom
+    if ((bColumn && aNewArea.getWidth()) || (!bColumn && aNewArea.getHeight()))
+    {
+        rTabView.UpdateSelectionOverlay();
+        SfxLokHelper::notifyInvalidation(rViewData.GetViewShell(), aNewArea.toString());
+    }
+
+    // Provide size in the payload, so clients don't have to query for that.
+    std::stringstream ss;
+    ss << aNewSize.Width() << ", " << aNewSize.Height();
+    OString sSize = ss.str().c_str();
+    ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(
+        rViewData.GetViewShell()->GetCurrentDocument());
+    SfxLokHelper::notifyDocumentSizeChanged(rViewData.GetViewShell(), sSize, pModel, false);
+}
+
 } // anonymous namespace
 
 OUString ScTabView::getRowColumnHeaders(const tools::Rectangle& rRectangle)
@@ -2836,167 +2997,6 @@ OString ScTabView::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes,
     return getJSONString(aTree).c_str();
 }
 
-class ScRangeProvider
-{
-public:
-    ScRangeProvider(const tools::Rectangle& rArea, bool bInPixels,
-                    ScViewData& rViewData, SCCOLROW nEnlargeX = 0,
-                    SCCOLROW nEnlargeY = 0):
-        mrViewData(rViewData),
-        mnEnlargeX(nEnlargeX),
-        mnEnlargeY(nEnlargeY)
-    {
-        tools::Rectangle aAreaPx = bInPixels ? rArea :
-            tools::Rectangle(rArea.Left() * mrViewData.GetPPTX(),
-                             rArea.Top() * mrViewData.GetPPTY(),
-                             rArea.Right() * mrViewData.GetPPTX(),
-                             rArea.Bottom() * mrViewData.GetPPTY());
-        calculateBounds(aAreaPx);
-    }
-
-    const ScRange& getCellRange() const
-    {
-        return maRange;
-    }
-
-    void getColPositions(long& rStartColPos, long& rEndColPos) const
-    {
-        rStartColPos = maBoundPositions.Left();
-        rEndColPos = maBoundPositions.Right();
-    }
-
-    void getRowPositions(long& rStartRowPos, long& rEndRowPos) const
-    {
-        rStartRowPos = maBoundPositions.Top();
-        rEndRowPos = maBoundPositions.Bottom();
-    }
-
-private:
-    void calculateBounds(const tools::Rectangle& rAreaPx)
-    {
-        long nLeftPx = 0, nRightPx = 0;
-        SCCOLROW nStartCol = -1, nEndCol = -1;
-        calculateDimensionBounds(rAreaPx.Left(), rAreaPx.Right(), true,
-                                 nStartCol, nEndCol, nLeftPx, nRightPx,
-                                 mnEnlargeX, mrViewData);
-        long nTopPx = 0, nBottomPx = 0;
-        SCCOLROW nStartRow = -1, nEndRow = -1;
-        calculateDimensionBounds(rAreaPx.Top(), rAreaPx.Bottom(), false,
-                                 nStartRow, nEndRow, nTopPx, nBottomPx,
-                                 mnEnlargeY, mrViewData);
-
-        maRange.aStart.Set(nStartCol, nStartRow, mrViewData.GetTabNo());
-        maRange.aEnd.Set(nEndCol, nEndRow, mrViewData.GetTabNo());
-
-        maBoundPositions.SetLeft(nLeftPx);
-        maBoundPositions.SetRight(nRightPx);
-        maBoundPositions.SetTop(nTopPx);
-        maBoundPositions.SetBottom(nBottomPx);
-    }
-
-    // All positions are in pixels.
-    static void calculateDimensionBounds(const long nStartPos, const long nEndPos,
-                                         bool bColumns, SCCOLROW& rStartIndex,
-                                         SCCOLROW& rEndIndex, long& rBoundStart,
-                                         long& rBoundEnd, SCCOLROW nEnlarge,
-                                         ScViewData& rViewData)
-    {
-        ScPositionHelper& rPosHelper = bColumns ? rViewData.GetLOKWidthHelper() :
-            rViewData.GetLOKHeightHelper();
-        const auto& rStartNearest = rPosHelper.getNearestByPosition(nStartPos);
-        const auto& rEndNearest = rPosHelper.getNearestByPosition(nEndPos);
-
-        ScBoundsProvider aBoundsProvider(rViewData, rViewData.GetTabNo(), bColumns);
-        aBoundsProvider.Compute(rStartNearest, rEndNearest, nStartPos, nEndPos);
-        aBoundsProvider.EnlargeBy(nEnlarge);
-        if (bColumns)
-        {
-            SCCOL nStartCol = -1, nEndCol = -1;
-            aBoundsProvider.GetStartIndexAndPosition(nStartCol, rBoundStart);
-            aBoundsProvider.GetEndIndexAndPosition(nEndCol, rBoundEnd);
-            rStartIndex = nStartCol;
-            rEndIndex = nEndCol;
-        }
-        else
-        {
-            SCROW nStartRow = -1, nEndRow = -1;
-            aBoundsProvider.GetStartIndexAndPosition(nStartRow, rBoundStart);
-            aBoundsProvider.GetEndIndexAndPosition(nEndRow, rBoundEnd);
-            rStartIndex = nStartRow;
-            rEndIndex = nEndRow;
-        }
-    }
-
-private:
-
-    ScRange maRange;
-    tools::Rectangle maBoundPositions;
-    ScViewData& mrViewData;
-    SCCOLROW mnEnlargeX;
-    SCCOLROW mnEnlargeY;
-};
-
-static void lcl_ExtendTiledDimension(bool bColumn, const SCCOLROW nEnd, const SCCOLROW nExtra,
-                                     ScTabView& rTabView, ScViewData& rViewData)
-{
-    ScDocument* pDoc = rViewData.GetDocument();
-    // If we are approaching current max tiled row/col, signal a size changed event
-    // and invalidate the involved area
-    SCCOLROW nMaxTiledIndex = bColumn ? rViewData.GetMaxTiledCol() : rViewData.GetMaxTiledRow();
-    SCCOLROW nHardLimit = !bColumn ? MAXTILEDROW : pDoc ? pDoc->MaxCol() : MAXCOL;
-
-    if (nMaxTiledIndex >= nHardLimit)
-        return;
-
-    if (nEnd <= nMaxTiledIndex - nExtra) // No need to extend.
-        return;
-
-    ScDocShell* pDocSh = rViewData.GetDocShell();
-    ScModelObj* pModelObj = pDocSh ?
-        comphelper::getUnoTunnelImplementation<ScModelObj>( pDocSh->GetModel() ) : nullptr;
-    Size aOldSize(0, 0);
-    if (pModelObj)
-        aOldSize = pModelObj->getDocumentSize();
-
-    SCCOLROW nNewMaxTiledIndex = std::min(std::max(nEnd, nMaxTiledIndex) + nExtra, nHardLimit);
-
-    if (bColumn)
-        rViewData.SetMaxTiledCol(nNewMaxTiledIndex);
-    else
-        rViewData.SetMaxTiledRow(nNewMaxTiledIndex);
-
-    Size aNewSize(0, 0);
-    if (pModelObj)
-        aNewSize = pModelObj->getDocumentSize();
-
-    if (aOldSize == aNewSize)
-        return;
-
-    if (!pDocSh)
-        return;
-
-    // New area extended to the right/bottom of the sheet after last col/row
-    // excluding overlapping area with aNewArea
-    tools::Rectangle aNewArea = bColumn ?
-        tools::Rectangle(aOldSize.getWidth(), 0, aNewSize.getWidth(), aNewSize.getHeight()):
-        tools::Rectangle(0, aOldSize.getHeight(), aNewSize.getWidth(), aNewSize.getHeight());
-
-    // Only invalidate if spreadsheet has extended to the right or bottom
-    if ((bColumn && aNewArea.getWidth()) || (!bColumn && aNewArea.getHeight()))
-    {
-        rTabView.UpdateSelectionOverlay();
-        SfxLokHelper::notifyInvalidation(rViewData.GetViewShell(), aNewArea.toString());
-    }
-
-    // Provide size in the payload, so clients don't have to query for that.
-    std::stringstream ss;
-    ss << aNewSize.Width() << ", " << aNewSize.Height();
-    OString sSize = ss.str().c_str();
-    ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(
-        rViewData.GetViewShell()->GetCurrentDocument());
-    SfxLokHelper::notifyDocumentSizeChanged(rViewData.GetViewShell(), sSize, pModel, false);
-}
-
 void ScTabView::extendTiledAreaIfNeeded()
 {
     SAL_INFO("sc.lok.header",
commit 3268f8e16c6b92ee10905cc326956d4d06a33455
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue May 19 10:41:53 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:56 2020 +0530

    lokit: scPrintTwipsMsgs: Extend the tiled-area limits...
    
    if the client visible area is "close" to these limits. Also
    send tile-invalidations for the new area uncovered.
    
    ** All this is done only if the flag scPrintTwipsMsgs is set.
    
    Change-Id: I3d6b8c6aaae1eb934030c5bdbc1094dc8be16a9f

diff --git a/sc/source/ui/inc/tabview.hxx b/sc/source/ui/inc/tabview.hxx
index 873d05047e46..b1881408b007 100644
--- a/sc/source/ui/inc/tabview.hxx
+++ b/sc/source/ui/inc/tabview.hxx
@@ -595,6 +595,7 @@ public:
     /// @see ScModelObj::getSheetGeometryData()
     OString getSheetGeometryData(bool bColumns, bool bRows, bool bSizes, bool bHidden,
                                  bool bFiltered, bool bGroups);
+    void extendTiledAreaIfNeeded();
 
     static void OnLOKNoteStateChanged(const ScPostIt* pNote);
 
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 5d4fb17eb0fd..0990cede1974 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -68,6 +68,7 @@
 #include <com/sun/star/script/XInvocation.hpp>
 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
 #include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/profilezone.hxx>
 #include <comphelper/servicehelper.hxx>
@@ -979,6 +980,14 @@ void ScModelObj::setClientVisibleArea(const tools::Rectangle& rRectangle)
 
     // Store the visible area so that we can use at places like shape insertion
     pViewData->setLOKVisibleArea(rRectangle);
+
+    if (comphelper::LibreOfficeKit::isCompatFlagSet(
+            comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+    {
+        ScTabView* pTabView = pViewData->GetView();
+        if (pTabView)
+            pTabView->extendTiledAreaIfNeeded();
+    }
 }
 
 void ScModelObj::setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden)
diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 53c811726029..c051547b08c0 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2836,4 +2836,264 @@ OString ScTabView::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes,
     return getJSONString(aTree).c_str();
 }
 
+class ScRangeProvider
+{
+public:
+    ScRangeProvider(const tools::Rectangle& rArea, bool bInPixels,
+                    ScViewData& rViewData, SCCOLROW nEnlargeX = 0,
+                    SCCOLROW nEnlargeY = 0):
+        mrViewData(rViewData),
+        mnEnlargeX(nEnlargeX),
+        mnEnlargeY(nEnlargeY)
+    {
+        tools::Rectangle aAreaPx = bInPixels ? rArea :
+            tools::Rectangle(rArea.Left() * mrViewData.GetPPTX(),
+                             rArea.Top() * mrViewData.GetPPTY(),
+                             rArea.Right() * mrViewData.GetPPTX(),
+                             rArea.Bottom() * mrViewData.GetPPTY());
+        calculateBounds(aAreaPx);
+    }
+
+    const ScRange& getCellRange() const
+    {
+        return maRange;
+    }
+
+    void getColPositions(long& rStartColPos, long& rEndColPos) const
+    {
+        rStartColPos = maBoundPositions.Left();
+        rEndColPos = maBoundPositions.Right();
+    }
+
+    void getRowPositions(long& rStartRowPos, long& rEndRowPos) const
+    {
+        rStartRowPos = maBoundPositions.Top();
+        rEndRowPos = maBoundPositions.Bottom();
+    }
+
+private:
+    void calculateBounds(const tools::Rectangle& rAreaPx)
+    {
+        long nLeftPx = 0, nRightPx = 0;
+        SCCOLROW nStartCol = -1, nEndCol = -1;
+        calculateDimensionBounds(rAreaPx.Left(), rAreaPx.Right(), true,
+                                 nStartCol, nEndCol, nLeftPx, nRightPx,
+                                 mnEnlargeX, mrViewData);
+        long nTopPx = 0, nBottomPx = 0;
+        SCCOLROW nStartRow = -1, nEndRow = -1;
+        calculateDimensionBounds(rAreaPx.Top(), rAreaPx.Bottom(), false,
+                                 nStartRow, nEndRow, nTopPx, nBottomPx,
+                                 mnEnlargeY, mrViewData);
+
+        maRange.aStart.Set(nStartCol, nStartRow, mrViewData.GetTabNo());
+        maRange.aEnd.Set(nEndCol, nEndRow, mrViewData.GetTabNo());
+
+        maBoundPositions.SetLeft(nLeftPx);
+        maBoundPositions.SetRight(nRightPx);
+        maBoundPositions.SetTop(nTopPx);
+        maBoundPositions.SetBottom(nBottomPx);
+    }
+
+    // All positions are in pixels.
+    static void calculateDimensionBounds(const long nStartPos, const long nEndPos,
+                                         bool bColumns, SCCOLROW& rStartIndex,
+                                         SCCOLROW& rEndIndex, long& rBoundStart,
+                                         long& rBoundEnd, SCCOLROW nEnlarge,
+                                         ScViewData& rViewData)
+    {
+        ScPositionHelper& rPosHelper = bColumns ? rViewData.GetLOKWidthHelper() :
+            rViewData.GetLOKHeightHelper();
+        const auto& rStartNearest = rPosHelper.getNearestByPosition(nStartPos);
+        const auto& rEndNearest = rPosHelper.getNearestByPosition(nEndPos);
+
+        ScBoundsProvider aBoundsProvider(rViewData, rViewData.GetTabNo(), bColumns);
+        aBoundsProvider.Compute(rStartNearest, rEndNearest, nStartPos, nEndPos);
+        aBoundsProvider.EnlargeBy(nEnlarge);
+        if (bColumns)
+        {
+            SCCOL nStartCol = -1, nEndCol = -1;
+            aBoundsProvider.GetStartIndexAndPosition(nStartCol, rBoundStart);
+            aBoundsProvider.GetEndIndexAndPosition(nEndCol, rBoundEnd);
+            rStartIndex = nStartCol;
+            rEndIndex = nEndCol;
+        }
+        else
+        {
+            SCROW nStartRow = -1, nEndRow = -1;
+            aBoundsProvider.GetStartIndexAndPosition(nStartRow, rBoundStart);
+            aBoundsProvider.GetEndIndexAndPosition(nEndRow, rBoundEnd);
+            rStartIndex = nStartRow;
+            rEndIndex = nEndRow;
+        }
+    }
+
+private:
+
+    ScRange maRange;
+    tools::Rectangle maBoundPositions;
+    ScViewData& mrViewData;
+    SCCOLROW mnEnlargeX;
+    SCCOLROW mnEnlargeY;
+};
+
+static void lcl_ExtendTiledDimension(bool bColumn, const SCCOLROW nEnd, const SCCOLROW nExtra,
+                                     ScTabView& rTabView, ScViewData& rViewData)
+{
+    ScDocument* pDoc = rViewData.GetDocument();
+    // If we are approaching current max tiled row/col, signal a size changed event
+    // and invalidate the involved area
+    SCCOLROW nMaxTiledIndex = bColumn ? rViewData.GetMaxTiledCol() : rViewData.GetMaxTiledRow();
+    SCCOLROW nHardLimit = !bColumn ? MAXTILEDROW : pDoc ? pDoc->MaxCol() : MAXCOL;
+
+    if (nMaxTiledIndex >= nHardLimit)
+        return;
+
+    if (nEnd <= nMaxTiledIndex - nExtra) // No need to extend.
+        return;
+
+    ScDocShell* pDocSh = rViewData.GetDocShell();
+    ScModelObj* pModelObj = pDocSh ?
+        comphelper::getUnoTunnelImplementation<ScModelObj>( pDocSh->GetModel() ) : nullptr;
+    Size aOldSize(0, 0);
+    if (pModelObj)
+        aOldSize = pModelObj->getDocumentSize();
+
+    SCCOLROW nNewMaxTiledIndex = std::min(std::max(nEnd, nMaxTiledIndex) + nExtra, nHardLimit);
+
+    if (bColumn)
+        rViewData.SetMaxTiledCol(nNewMaxTiledIndex);
+    else
+        rViewData.SetMaxTiledRow(nNewMaxTiledIndex);
+
+    Size aNewSize(0, 0);
+    if (pModelObj)
+        aNewSize = pModelObj->getDocumentSize();
+
+    if (aOldSize == aNewSize)
+        return;
+
+    if (!pDocSh)
+        return;
+
+    // New area extended to the right/bottom of the sheet after last col/row
+    // excluding overlapping area with aNewArea
+    tools::Rectangle aNewArea = bColumn ?
+        tools::Rectangle(aOldSize.getWidth(), 0, aNewSize.getWidth(), aNewSize.getHeight()):
+        tools::Rectangle(0, aOldSize.getHeight(), aNewSize.getWidth(), aNewSize.getHeight());
+
+    // Only invalidate if spreadsheet has extended to the right or bottom
+    if ((bColumn && aNewArea.getWidth()) || (!bColumn && aNewArea.getHeight()))
+    {
+        rTabView.UpdateSelectionOverlay();
+        SfxLokHelper::notifyInvalidation(rViewData.GetViewShell(), aNewArea.toString());
+    }
+
+    // Provide size in the payload, so clients don't have to query for that.
+    std::stringstream ss;
+    ss << aNewSize.Width() << ", " << aNewSize.Height();
+    OString sSize = ss.str().c_str();
+    ScModelObj* pModel = comphelper::getUnoTunnelImplementation<ScModelObj>(
+        rViewData.GetViewShell()->GetCurrentDocument());
+    SfxLokHelper::notifyDocumentSizeChanged(rViewData.GetViewShell(), sSize, pModel, false);
+}
+
+void ScTabView::extendTiledAreaIfNeeded()
+{
+    SAL_INFO("sc.lok.header",
+        "extendTiledAreaIfNeeded: START: ClientView: ColRange["
+        << mnLOKStartHeaderCol << "," << mnLOKEndHeaderCol << "] "
+        << "RowRange[" << mnLOKStartHeaderRow << "," << mnLOKEndHeaderRow << "] "
+        << "MaxTiledCol = " << aViewData.GetMaxTiledCol()
+        << " MaxTiledRow = " << aViewData.GetMaxTiledRow());
+
+    const tools::Rectangle rVisArea = aViewData.getLOKVisibleArea();
+    if (rVisArea.Top() >= rVisArea.Bottom() ||
+        rVisArea.Left() >= rVisArea.Right())
+        return;
+
+    // Needed for conditional updating of visible-range/formula.
+    tools::Rectangle aOldVisCellRange(mnLOKStartHeaderCol + 1, mnLOKStartHeaderRow + 1,
+                                      mnLOKEndHeaderCol, mnLOKEndHeaderRow);
+
+    ScRangeProvider aRangeProvider(rVisArea, /* bInPixels */ false, aViewData,
+                                   /* nEnlargeX */ 2, /* nEnlargeY */ 2);
+    // Index bounds.
+    const ScRange& rCellRange = aRangeProvider.getCellRange();
+    const SCCOL nStartCol = rCellRange.aStart.Col();
+    const SCCOL nEndCol = rCellRange.aEnd.Col();
+    const SCROW nStartRow = rCellRange.aStart.Row();
+    const SCROW nEndRow = rCellRange.aEnd.Row();
+
+    // Column/Row positions.
+    long nStartColPos, nEndColPos, nStartRowPos, nEndRowPos;
+    aRangeProvider.getColPositions(nStartColPos, nEndColPos);
+    aRangeProvider.getRowPositions(nStartRowPos, nEndRowPos);
+
+    ScPositionHelper& rWidthHelper = aViewData.GetLOKWidthHelper();
+    ScPositionHelper& rHeightHelper = aViewData.GetLOKHeightHelper();
+
+    // Update mnLOKStartHeaderCol and mnLOKEndHeaderCol members.
+    // These are consulted in some ScGridWindow methods.
+    if (mnLOKStartHeaderCol != nStartCol)
+    {
+        rWidthHelper.removeByIndex(mnLOKStartHeaderCol);
+        rWidthHelper.insert(nStartCol, nStartColPos);
+        mnLOKStartHeaderCol = nStartCol;
+    }
+
+    if (mnLOKEndHeaderCol != nEndCol)
+    {
+        rWidthHelper.removeByIndex(mnLOKEndHeaderCol);
+        rWidthHelper.insert(nEndCol, nEndColPos);
+        mnLOKEndHeaderCol = nEndCol;
+    }
+
+    // Update mnLOKStartHeaderRow and mnLOKEndHeaderRow members.
+    // These are consulted in some ScGridWindow methods.
+    if (mnLOKStartHeaderRow != nStartRow)
+    {
+        rHeightHelper.removeByIndex(mnLOKStartHeaderRow);
+        rHeightHelper.insert(nStartRow, nStartRowPos);
+        mnLOKStartHeaderRow = nStartRow;
+    }
+
+    if (mnLOKEndHeaderRow != nEndRow)
+    {
+        rHeightHelper.removeByIndex(mnLOKEndHeaderRow);
+        rHeightHelper.insert(nEndRow, nEndRowPos);
+        mnLOKEndHeaderRow = nEndRow;
+    }
+
+    constexpr SCCOL nMinExtraCols = 10;
+    SCCOL nExtraCols = std::max<SCCOL>(nMinExtraCols, nEndCol - nStartCol);
+    // If we are approaching current max tiled column, signal a size changed event
+    // and invalidate the involved area.
+    lcl_ExtendTiledDimension(/* bColumn */ true, nEndCol, nExtraCols, *this, aViewData);
+
+    constexpr SCROW nMinExtraRows = 25;
+    SCROW nExtraRows = std::max(nMinExtraRows, nEndRow - nStartRow);
+    // If we are approaching current max tiled row, signal a size changed event
+    // and invalidate the involved area.
+    lcl_ExtendTiledDimension(/* bColumn */ false, nEndRow, nExtraRows, *this, aViewData);
+
+    vcl::Region aNewVisCellRange(
+            tools::Rectangle(mnLOKStartHeaderCol + 1, mnLOKStartHeaderRow + 1,
+                             mnLOKEndHeaderCol, mnLOKEndHeaderRow));
+    aNewVisCellRange.Exclude(aOldVisCellRange);
+    tools::Rectangle aChangedCellRange = aNewVisCellRange.GetBoundRect();
+    if (!aChangedCellRange.IsEmpty())
+    {
+        UpdateVisibleRange();
+        UpdateFormulas(aChangedCellRange.Left(), aChangedCellRange.Top(),
+                       aChangedCellRange.Right(), aChangedCellRange.Bottom());
+    }
+
+    SAL_INFO("sc.lok.header",
+        "extendTiledAreaIfNeeded: END: ClientView: ColRange["
+        << mnLOKStartHeaderCol << "," << mnLOKEndHeaderCol << "] "
+        << "RowRange[" << mnLOKStartHeaderRow << "," << mnLOKEndHeaderRow << "] "
+        << "MaxTiledCol = " << aViewData.GetMaxTiledCol()
+        << " MaxTiledRow = " << aViewData.GetMaxTiledRow());
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 3389d07341097be5b10df6cb91a6fdf48bfc2c86
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Thu May 21 01:48:03 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:56 2020 +0530

    lokit: notify clients of various sheet geometry invalidations
    
    if the new feature flag scPrintTwipsMsgs is set.
    
    Change-Id: Ia36b9f3835115fb6f30e4e8f57d5d7a1b57df609

diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index d9f89078e6e6..6da29b7d0860 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -273,11 +273,19 @@ void ScUndoInsertCells::DoChange( const bool bUndo )
 
         if (comphelper::LibreOfficeKit::isActive())
         {
-            if (eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER || eCmd == INS_CELLSRIGHT)
-                ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER,  pViewShell->GetViewData().GetTabNo());
-
-            if (eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_CELLSDOWN)
-                ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER,  pViewShell->GetViewData().GetTabNo());
+            bool bColumns = (eCmd == INS_INSCOLS_BEFORE || eCmd == INS_INSCOLS_AFTER || eCmd == INS_CELLSRIGHT);
+            bool bRows = (eCmd == INS_INSROWS_BEFORE || eCmd == INS_INSROWS_AFTER || eCmd == INS_CELLSDOWN);
+            SCTAB nTab = pViewShell->GetViewData().GetTabNo();
+            if (bColumns)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, nTab);
+
+            if (bRows)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, nTab);
+
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                    bColumns, bRows,
+                    true /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+                    true /* bGroups */, nTab);
         }
     }
 }
@@ -534,11 +542,20 @@ void ScUndoDeleteCells::DoChange( const bool bUndo )
     {
         if (comphelper::LibreOfficeKit::isActive())
         {
-            if (eCmd == DelCellCmd::Cols || eCmd == DelCellCmd::CellsLeft)
-                ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER,  pViewShell->GetViewData().GetTabNo());
+            bool bColumns = (eCmd == DelCellCmd::Cols || eCmd == DelCellCmd::CellsLeft);
+            bool bRows = (eCmd == DelCellCmd::Rows || eCmd == DelCellCmd::CellsUp);
+            SCTAB nTab = pViewShell->GetViewData().GetTabNo();
+
+            if (bColumns)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, nTab);
+
+            if (bRows)
+                ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, nTab);
 
-            if (eCmd == DelCellCmd::Rows || eCmd == DelCellCmd::CellsUp)
-                ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER,  pViewShell->GetViewData().GetTabNo());
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                    bColumns, bRows,
+                    true /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+                    true /* bGroups */, nTab);
         }
 
     }
diff --git a/sc/source/ui/undo/undoblk2.cxx b/sc/source/ui/undo/undoblk2.cxx
index 9b4de7f89f62..584d610e3315 100644
--- a/sc/source/ui/undo/undoblk2.cxx
+++ b/sc/source/ui/undo/undoblk2.cxx
@@ -125,9 +125,14 @@ void ScUndoWidthOrHeight::Undo()
 
     if (pViewShell)
     {
+        SCTAB nCurrentTab = pViewShell->GetViewData().GetTabNo();
+        bool bAffectsVisibility = (eMode != SC_SIZE_ORIGINAL && eMode != SC_SIZE_VISOPT);
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                bWidth /* bColumns */, !bWidth /* bRows */,
+                true /* bSizes*/, bAffectsVisibility /* bHidden */, bAffectsVisibility /* bFiltered */,
+                false /* bGroups */, nCurrentTab);
         pViewShell->UpdateScrollBars(bWidth ? COLUMN_HEADER : ROW_HEADER);
 
-        SCTAB nCurrentTab = pViewShell->GetViewData().GetTabNo();
         if ( nCurrentTab < nStartTab || nCurrentTab > nEndTab )
             pViewShell->SetTabNo( nStartTab );
     }
diff --git a/sc/source/ui/undo/undodat.cxx b/sc/source/ui/undo/undodat.cxx
index 373908540f7c..159a6be32c13 100644
--- a/sc/source/ui/undo/undodat.cxx
+++ b/sc/source/ui/undo/undodat.cxx
@@ -100,6 +100,9 @@ void ScUndoDoOutline::Undo()
     else
         pUndoDoc->CopyToDocument(0, nStart, nTab, rDoc.MaxCol(), nEnd, nTab, InsertDeleteFlags::NONE, false, rDoc);
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            true /* bGroups */, nTab);
     pViewShell->UpdateScrollBars();
 
     pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top);
@@ -179,6 +182,10 @@ void ScUndoMakeOutline::Undo()
 
     pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+            bColumns /* bColumns */, !bColumns /* bRows */,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            true /* bGroups */, nTab);
     ScTabViewShell::notifyAllViewsHeaderInvalidation( bColumns, nTab );
 
     EndUndo();
@@ -262,6 +269,9 @@ void ScUndoOutlineLevel::Undo()
 
     rDoc.UpdatePageBreaks( nTab );
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            true /* bGroups */, nTab);
     pViewShell->UpdateScrollBars();
 
     SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
@@ -354,6 +364,9 @@ void ScUndoOutlineBlock::Undo()
 
     rDoc.UpdatePageBreaks( nTab );
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(true /* bColumns */, true /* bRows */,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            true /* bGroups */, nTab);
     pViewShell->UpdateScrollBars();
 
     SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
@@ -449,6 +462,10 @@ void ScUndoRemoveAllOutlines::Undo()
 
     pDocShell->PostPaint(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab,PaintPartFlags::Grid|PaintPartFlags::Left|PaintPartFlags::Top|PaintPartFlags::Size);
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+            true /* bColumns */, true /* bRows */,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            true /* bGroups */, nTab);
     ScTabViewShell::notifyAllViewsHeaderInvalidation(BOTH_HEADERS, nTab);
 
     EndUndo();
@@ -814,6 +831,10 @@ void ScUndoQuery::Undo()
 
     // invalidate cache positions and update cursor and selection
     pViewShell->OnLOKShowHideColRow(/*bColumns*/ false, aQueryParam.nRow1 - 1);
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+            false /* bColumns */, true /* bRows */,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            false /* bGroups */, nTab);
     ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, nTab);
 
     //  Paint
@@ -1333,6 +1354,10 @@ void ScUndoRepeatDB::Undo()
     if (xUndoDB)
         rDoc.SetDBCollection(std::unique_ptr<ScDBCollection>(new ScDBCollection(*xUndoDB)), true);
 
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(false /* bColumns */, true /* bRows */,
+            false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+            false /* bGroups */, nTab);
+
     SCTAB nVisTab = pViewShell->GetViewData().GetTabNo();
     if ( nVisTab != nTab )
         pViewShell->SetTabNo( nTab );
diff --git a/sc/source/ui/view/dbfunc.cxx b/sc/source/ui/view/dbfunc.cxx
index 74d211d02683..d76b5ce37b9f 100644
--- a/sc/source/ui/view/dbfunc.cxx
+++ b/sc/source/ui/view/dbfunc.cxx
@@ -257,6 +257,10 @@ void ScDBFunc::Query( const ScQueryParam& rQueryParam, const ScRange* pAdvSource
 
         if (!bCopy)
         {
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                false /* bColumns */, true /* bRows */,
+                false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+                false /* bGroups */, nTab);
             UpdateScrollBars(ROW_HEADER);
             SelectionChanged();     // for attribute states (filtered rows are ignored)
         }
diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx
index d7faee139d0c..cdc0324ee408 100644
--- a/sc/source/ui/view/dbfunc3.cxx
+++ b/sc/source/ui/view/dbfunc3.cxx
@@ -94,6 +94,9 @@ void ScDBFunc::MakeOutline( bool bColumns, bool bRecord )
         aFunc.MakeOutline( aRange, bColumns, bRecord, false );
 
         ScTabViewShell::notifyAllViewsHeaderInvalidation(bColumns, GetViewData().GetTabNo());
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns, false /* bSizes*/,
+                                                            false /* bHidden */, false /* bFiltered */,
+                                                            true /* bGroups */, GetViewData().GetTabNo());
     }
     else
         ErrorMessage(STR_NOMULTISELECT);
@@ -111,6 +114,9 @@ void ScDBFunc::RemoveOutline( bool bColumns, bool bRecord )
         aFunc.RemoveOutline( aRange, bColumns, bRecord, false );
 
         ScTabViewShell::notifyAllViewsHeaderInvalidation(bColumns, GetViewData().GetTabNo());
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns, false /* bSizes*/,
+                                                            true /* bHidden */, true /* bFiltered */,
+                                                            true /* bGroups */, GetViewData().GetTabNo());
     }
     else
         ErrorMessage(STR_NOMULTISELECT);
@@ -191,6 +197,9 @@ void ScDBFunc::RemoveAllOutlines( bool bRecord )
 
     if (bOk)
     {
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(true /* bColumns */, true /* bRows */, false /* bSizes*/,
+                                                            true /* bHidden */, true /* bFiltered */,
+                                                            true /* bGroups */, nTab);
         UpdateScrollBars(BOTH_HEADERS);
     }
 }
@@ -225,7 +234,12 @@ void ScDBFunc::SelectLevel( bool bColumns, sal_uInt16 nLevel, bool bRecord )
     bool bOk = aFunc.SelectLevel( nTab, bColumns, nLevel, bRecord, true/*bPaint*/ );
 
     if (bOk)
+    {
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns, false /* bSizes*/,
+                                                            true /* bHidden */, true /* bFiltered */,
+                                                            true /* bGroups */, nTab);
         UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
+    }
 }
 
 // show individual outline groups
@@ -253,7 +267,12 @@ void ScDBFunc::ShowOutline( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry,
     aFunc.ShowOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint );
 
     if ( bPaint )
+    {
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns, false /* bSizes*/,
+                                                            true /* bHidden */, true /* bFiltered */,
+                                                            true /* bGroups */, nTab);
         UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
+    }
 }
 
 // hide individual outline groups
@@ -267,7 +286,12 @@ void ScDBFunc::HideOutline( bool bColumns, sal_uInt16 nLevel, sal_uInt16 nEntry,
     bool bOk = aFunc.HideOutline( nTab, bColumns, nLevel, nEntry, bRecord, bPaint );
 
     if ( bOk && bPaint )
+    {
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColumns, !bColumns, false /* bSizes*/,
+                                                            true /* bHidden */, true /* bFiltered */,
+                                                            true /* bGroups */, nTab);
         UpdateScrollBars(bColumns ? COLUMN_HEADER : ROW_HEADER);
+    }
 }
 
 // menu status: show/hide marked range
@@ -359,7 +383,12 @@ void ScDBFunc::ShowMarkedOutlines( bool bRecord )
         ScOutlineDocFunc aFunc(*pDocSh);
         bool bDone = aFunc.ShowMarkedOutlines( aRange, bRecord );
         if (bDone)
+        {
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(true, true,
+                false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+                true /* bGroups */, GetViewData().GetTabNo());
             UpdateScrollBars();
+        }
     }
     else
         ErrorMessage(STR_NOMULTISELECT);
@@ -376,7 +405,12 @@ void ScDBFunc::HideMarkedOutlines( bool bRecord )
         ScOutlineDocFunc aFunc(*pDocSh);
         bool bDone = aFunc.HideMarkedOutlines( aRange, bRecord );
         if (bDone)
+        {
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(true, true,
+                false /* bSizes*/, true /* bHidden */, true /* bFiltered */,
+                true /* bGroups */, GetViewData().GetTabNo());
             UpdateScrollBars();
+        }
     }
     else
         ErrorMessage(STR_NOMULTISELECT);
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index d26874ea47f4..e2e1d73d4794 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -537,6 +537,43 @@ void ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bool bColumns, bool bRo
                                                          bool bHidden, bool bFiltered, bool bGroups,
                                                          SCTAB nCurrentTabIndex)
 {
+    if (!comphelper::LibreOfficeKit::isActive() ||
+            !comphelper::LibreOfficeKit::isCompatFlagSet(
+                comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+        return;
+
+    if (!bColumns && !bRows)
+        return;
+
+    bool bAllTypes = bSizes && bHidden && bFiltered && bGroups;
+    bool bAllDims = bColumns && bRows;
+    OString aPayload = bAllDims ? "all" : bColumns ? "columns" : "rows";
+
+    if (!bAllTypes)
+    {
+        if (bSizes)
+            aPayload += " sizes";
+
+        if (bHidden)
+            aPayload += " hidden";
+
+        if (bFiltered)
+            aPayload += " filtered";
+
+        if (bGroups)
+            aPayload += " groups";
+    }
+
+    SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+    while (pViewShell)
+    {
+        ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell);
+        if (pTabViewShell && (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex))
+        {
+            pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY, aPayload.getStr());
+        }
+        pViewShell = SfxViewShell::GetNext(*pViewShell);
+    }
 }
 
 bool ScTabViewShell::isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx
index 09e5b87526cb..916cebd3cb43 100644
--- a/sc/source/ui/view/viewfun2.cxx
+++ b/sc/source/ui/view/viewfun2.cxx
@@ -175,7 +175,14 @@ bool ScViewFunc::AdjustBlockHeight( bool bPaint, ScMarkData* pMarkData )
         pDocSh->UpdateOle(&GetViewData());
 
     if (comphelper::LibreOfficeKit::isActive())
-        ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo());
+    {
+        SCTAB nTab = GetViewData().GetTabNo();
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                false /* bColumns */, true /* bRows */,
+                true /* bSizes*/, false /* bHidden */, false /* bFiltered */,
+                false /* bGroups */, nTab);
+        ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, nTab);
+    }
 
     return bAnyChanged;
 }
@@ -224,7 +231,13 @@ bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow )
                                             PaintPartFlags::Grid | PaintPartFlags::Left );
 
     if (comphelper::LibreOfficeKit::isActive())
-        ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo());
+    {
+        ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
+                false /* bColumns */, true /* bRows */,
+                true /* bSizes*/, false /* bHidden */, false /* bFiltered */,
+                false /* bGroups */, nTab);
+        ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, nTab);
+    }
 
     return bChanged;
 }
diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx
index d70b2742b6f6..30e2b021461d 100644
--- a/sc/source/ui/view/viewfunc.cxx
+++ b/sc/source/ui/view/viewfunc.cxx
@@ -1627,6 +1627,10 @@ bool ScViewFunc::InsertCells( InsCellCmd eCmd, bool bRecord, bool bPartOfPaste )
 
                 if (bInsertRows)
                     ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo());
+
+                ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bInsertCols, bInsertRows, true /* bSizes*/,
+                                                                    true /* bHidden */, true /* bFiltered */,
+                                                                    true /* bGroups */, GetViewData().GetTabNo());
             }
         }
         OUString aStartAddress =  aRange.aStart.GetColRowString();
@@ -1700,11 +1704,17 @@ void ScViewFunc::DeleteCells( DelCellCmd eCmd )
 
         if (comphelper::LibreOfficeKit::isActive())
         {
-            if (eCmd == DelCellCmd::Cols)
+            bool bColsDeleted = (eCmd == DelCellCmd::Cols);
+            bool bRowsDeleted = (eCmd == DelCellCmd::Rows);
+            if (bColsDeleted)
                 ScTabViewShell::notifyAllViewsHeaderInvalidation(COLUMN_HEADER, GetViewData().GetTabNo());
 
-            if (eCmd == DelCellCmd::Rows)
+            if (bRowsDeleted)
                 ScTabViewShell::notifyAllViewsHeaderInvalidation(ROW_HEADER, GetViewData().GetTabNo());
+
+            ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bColsDeleted, bRowsDeleted, true /* bSizes*/,
+                                                                true /* bHidden */, true /* bFiltered */,
+                                                                true /* bGroups */, GetViewData().GetTabNo());
         }
     }
     else
@@ -2250,6 +2260,10 @@ void ScViewFunc::SetWidthOrHeight(
     for (const SCTAB& nTab : aMarkData)
         rDoc.UpdatePageBreaks( nTab );
 
+    bool bAffectsVisibility = (eMode != SC_SIZE_ORIGINAL && eMode != SC_SIZE_VISOPT);
+    ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bWidth /* bColumns */, !bWidth /* bRows */,
+            true /* bSizes*/, bAffectsVisibility /* bHidden */, bAffectsVisibility /* bFiltered */,
+            false /* bGroups */, nCurTab);
     GetViewData().GetView()->UpdateScrollBars(bWidth ? COLUMN_HEADER : ROW_HEADER);
 
     {
commit f6685707441770e7141b7b31fed1c2ddf550e297
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue May 19 12:42:33 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:55 2020 +0530

    lokit: add new callback type LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY
    
    This is to notify the clients about changes in current sheet's geometry
    data.
    
    Change-Id: I478d2e646606320399905d7b15881a165a53146d

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 4c6f16e2ccd0..942dc2be7310 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1407,6 +1407,7 @@ void CallbackFlushHandler::queue(const int type, const char* data)
         case LOK_CALLBACK_INVALIDATE_HEADER:
         case LOK_CALLBACK_WINDOW:
         case LOK_CALLBACK_CALC_FUNCTION_LIST:
+        case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY:
         {
             const auto& pos = std::find_if(m_queue.rbegin(), m_queue.rend(),
                     [type] (const queue_type::value_type& elem) { return (elem.Type == type); });
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 32fd9f657a5a..c091778a6389 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -747,6 +747,20 @@ typedef enum
      * }
      */
     LOK_CALLBACK_FORM_FIELD_BUTTON = 49,
+
+    /**
+     * This is Calc specific. Indicates that some or all of the current sheet's
+     * geometry data has changed. Clients must request a full or partial sheet
+     * geometry data set.
+     *
+     * The payload specifies what part of the sheet geometry data has changed.
+     * The payload format is:
+     * 'all|rows|columns [sizes [hidden [filtered [groups]]]]'
+     *
+     * For example, the payload 'rows sizes groups' indicates that the row heights
+     * and row-groups data have changed.
+     */
+    LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY = 50,
 }
 LibreOfficeKitCallbackType;
 
@@ -875,6 +889,8 @@ static inline const char* lokCallbackTypeToString(int nType)
         return "LOK_CALLBACK_TAB_STOP_LIST";
     case LOK_CALLBACK_FORM_FIELD_BUTTON:
         return "LOK_CALLBACK_FORM_FIELD_BUTTON";
+    case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY:
+        return "LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY";
     }
 
     assert(!"Unknown LibreOfficeKitCallbackType type.");
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 75deee7a38a0..3c09d7647457 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -1400,6 +1400,7 @@ callback (gpointer pData)
     case LOK_CALLBACK_CALC_FUNCTION_LIST:
     case LOK_CALLBACK_TAB_STOP_LIST:
     case LOK_CALLBACK_FORM_FIELD_BUTTON:
+    case LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY:
     {
         // TODO: Implement me
         break;
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index fad4de239c35..467cf12ef99b 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -388,6 +388,11 @@ public:
     /// Emits a LOK_CALLBACK_INVALIDATE_HEADER for all views whose current tab is equal to nCurrentTabIndex
     static void notifyAllViewsHeaderInvalidation(HeaderType eHeaderType, SCTAB nCurrentTabIndex);
     static void notifyAllViewsHeaderInvalidation(bool Columns, SCTAB nCurrentTabIndex);
+    /// Emits a LOK_CALLBACK_INVALIDATE_SHEET_GEOMETRY for all views whose current tab
+    /// is equal to nCurrentTabIndex
+    static void notifyAllViewsSheetGeomInvalidation(bool bColumns, bool bRows, bool bSizes,
+                                                    bool bHidden, bool bFiltered, bool bGroups,
+                                                    SCTAB nCurrentTabIndex);
     static bool isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd);
     css::uno::Reference<css::drawing::XShapes> getSelectedXShapes();
     static  css::uno::Reference<css::datatransfer::XTransferable2> GetClipData(vcl::Window* pWin);
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index afb406b4863a..d26874ea47f4 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -533,6 +533,12 @@ void ScTabViewShell::notifyAllViewsHeaderInvalidation(bool bColumns, SCTAB nCurr
     ScTabViewShell::notifyAllViewsHeaderInvalidation(eHeaderType, nCurrentTabIndex);
 }
 
+void ScTabViewShell::notifyAllViewsSheetGeomInvalidation(bool bColumns, bool bRows, bool bSizes,
+                                                         bool bHidden, bool bFiltered, bool bGroups,
+                                                         SCTAB nCurrentTabIndex)
+{
+}
+
 bool ScTabViewShell::isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd)
 {
     if (comphelper::LibreOfficeKit::isActive())
commit be7c109de9ae2b1849951e7eb3a4cc2d9a719605
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue May 19 13:37:04 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:54 2020 +0530

    lokit: Introduce new flag "sc_print_twips_msgs"...
    
    for conditioning all changes needed to allow calc messages in print
    twips coordinates.
    
    Change-Id: I407b4d4d4e0a1dfb2c4339cafa10b368b437c82d

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 44f28454c8f8..4c6f16e2ccd0 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5887,6 +5887,9 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
             else if (it == "sc_no_grid_bg")
                 comphelper::LibreOfficeKit::setCompatFlag(
                     comphelper::LibreOfficeKit::Compat::scNoGridBackground);
+            else if (it == "sc_print_twips_msgs")
+                comphelper::LibreOfficeKit::setCompatFlag(
+                    comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
         }
     }
 
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index 88901a24d991..dfbc1a2ce6c0 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -86,6 +86,7 @@ enum Compat : sal_uInt32
 {
     none = 0,
     scNoGridBackground = 1,
+    scPrintTwipsMsgs = 2,
 };
 /// Set compatibility flags
 COMPHELPER_DLLPUBLIC void setCompatFlag(Compat flag);
commit 8173d6894e46c8522c29ac233fa6a7a3c856de2f
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Wed May 13 22:33:44 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:53 2020 +0530

    add row/col limits to the JSON
    
    Change-Id: I92cead8212f30d0cc9b811be21b6639830e84fa4

diff --git a/sc/source/ui/view/tabview.cxx b/sc/source/ui/view/tabview.cxx
index 3e2f2fa3bdf5..53c811726029 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2765,6 +2765,8 @@ OString ScTabView::getSheetGeometryData(bool bColumns, bool bRows, bool bSizes,
 {
     boost::property_tree::ptree aTree;
     aTree.put("commandName", ".uno:SheetGeometryData");
+    aTree.put("maxtiledcolumn", MAXCOL);
+    aTree.put("maxtiledrow", MAXTILEDROW);
 
     auto getJSONString = [](const boost::property_tree::ptree& rTree) {
         std::stringstream aStream;
commit 3304f17fee8ca8b24acc7efae0f2241193bf9630
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue May 12 10:40:37 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:53 2020 +0530

    lokit: table-outline: skip empty collections...
    
    while encoding the information as string.
    
    Change-Id: I890efc4a9b60125c68c663a69569864308fdbdcf

diff --git a/sc/source/core/data/olinetab.cxx b/sc/source/core/data/olinetab.cxx
index 19553c52cdbc..d61b16564bd3 100644
--- a/sc/source/core/data/olinetab.cxx
+++ b/sc/source/core/data/olinetab.cxx
@@ -747,7 +747,11 @@ OString ScOutlineArray::dumpAsString() const
     OString aOutput;
     const char* pLevelSep = " ";
     for (const auto& rCollection : aCollections)
+    {
+        if (rCollection.empty())
+            continue;
         aOutput += rCollection.dumpAsString() + pLevelSep;
+    }
 
     return aOutput;
 }
commit e6c0b7e723d165cd61321055f4d10c6374cffcba
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Fri May 8 13:27:50 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:52 2020 +0530

    Unit tests for ITiledRenderable::getSheetGeometryData()
    
    (Testing of groups/ouline case is not included)
    
    Change-Id: Ia53e5489c376d2d86461a9fd3db4f5b7dc963b99

diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 7bdf8f189239..7c99525fcecd 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -106,6 +106,8 @@ public:
     void testGetRowColumnHeadersInvalidation();
     void testJumpHorizontallyInvalidation();
     void testJumpToLastRowInvalidation();
+    void testSheetGeometryDataInvariance();
+    void testSheetGeometryDataCorrectness();
 
     CPPUNIT_TEST_SUITE(ScTiledRenderingTest);
     CPPUNIT_TEST(testRowColumnHeaders);
@@ -147,6 +149,8 @@ public:
     CPPUNIT_TEST(testGetRowColumnHeadersInvalidation);
     CPPUNIT_TEST(testJumpHorizontallyInvalidation);
     CPPUNIT_TEST(testJumpToLastRowInvalidation);
+    CPPUNIT_TEST(testSheetGeometryDataInvariance);
+    CPPUNIT_TEST(testSheetGeometryDataCorrectness);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -1884,6 +1888,349 @@ void ScTiledRenderingTest::testRowColumnHeaders()
     SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
 }
 
+// Helper structs for setup and testing of ScModelObj::getSheetGeometryData()
+struct SpanEntry
+{
+    size_t nVal;
+    SCCOLROW nEnd;
+};
+
+struct SheetDimData
+{
+    typedef std::vector<SpanEntry> SpanList;
+    SpanList aSizes;
+    SpanList aHidden;
+    SpanList aFiltered;
+    // TODO: Add group info too to test.
+
+    void setDataToDoc(ScDocument* pDoc, bool bCol) const
+    {
+        SCCOLROW nStart = 0;
+        // sizes
+        for (const auto& rSpan : aSizes)
+        {
+            if (bCol)
+            {
+                for (SCCOLROW nIdx = nStart; nIdx <= rSpan.nEnd; ++nIdx)
+                    pDoc->SetColWidthOnly(nIdx, 0, rSpan.nVal);
+            }
+            else
+                pDoc->SetRowHeightOnly(nStart, rSpan.nEnd, 0, rSpan.nVal);
+
+            nStart = rSpan.nEnd + 1;
+        }
+
+        nStart = 0;
+        // hidden
+        for (const auto& rSpan : aHidden)
+        {
+            if (bCol)
+                pDoc->SetColHidden(nStart, rSpan.nEnd, 0, rSpan.nVal);
+            else
+                pDoc->SetRowHidden(nStart, rSpan.nEnd, 0, rSpan.nVal);
+
+            nStart = rSpan.nEnd + 1;
+        }
+
+        // There is no ScDocument interface to set ScTable::mpFilteredCols
+        // It seems ScTable::mpFilteredCols is not really used !?
+        if (bCol)
+            return;
+
+        nStart = 0;
+        // filtered
+        for (const auto& rSpan : aFiltered)
+        {
+            pDoc->SetRowFiltered(nStart, rSpan.nEnd, 0, rSpan.nVal);
+            nStart = rSpan.nEnd + 1;
+        }
+    }
+
+    void testPropertyTree(const boost::property_tree::ptree& rTree, bool bCol) const
+    {
+        struct SpanListWithKey
+        {
+            OString aKey;
+            const SpanList& rSpanList;
+        };
+
+        const SpanListWithKey aPairList[] = {
+            { "sizes",    aSizes    },
+            { "hidden",   aHidden   },
+            { "filtered", aFiltered }
+        };
+
+        for (const auto& rEntry : aPairList)
+        {
+            // There is no ScDocument interface to set ScTable::mpFilteredCols
+            // It seems ScTable::mpFilteredCols is not really used !?
+            if (bCol && rEntry.aKey == "filtered")
+                continue;
+
+            bool bBooleanValue = rEntry.aKey != "sizes";
+            OString aExpectedEncoding;
+            bool bFirst = true;
+            for (const auto& rSpan : rEntry.rSpanList)
+            {
+                size_t nVal = rSpan.nVal;
+                if (bBooleanValue && bFirst)
+                    nVal = static_cast<bool>(nVal);
+                if (!bBooleanValue || bFirst)
+                    aExpectedEncoding += OString::number(nVal) + ":";
+                aExpectedEncoding += OString::number(rSpan.nEnd) + " ";
+                bFirst = false;
+            }
+
+            // Get the tree's value for the property key ("sizes"/"hidden"/"filtered").
+            OString aTreeValue = rTree.get<std::string>(rEntry.aKey.getStr()).c_str();
+
+            CPPUNIT_ASSERT_EQUAL(aExpectedEncoding, aTreeValue);
+        }
+    }
+};
+
+class SheetGeometryData
+{
+    SheetDimData aCols;
+    SheetDimData aRows;
+
+public:
+
+    SheetGeometryData()
+    {
+        aCols = {
+            // width spans
+            { { STD_COL_WIDTH, MAXCOL } },
+            // hidden spans
+            { { 0,             MAXCOL } },
+            // filtered spans
+            { { 0,             MAXCOL } }
+        };
+
+        aRows = {
+            // height spans
+            { { ScGlobal::nStdRowHeight, MAXROW } },
+            // hidden spans
+            { { 0,                       MAXROW } },
+            // filtered spans
+            { { 0,                       MAXROW } }
+        };
+    }
+
+    SheetGeometryData(const SheetDimData& rCols, const SheetDimData& rRows) :
+        aCols(rCols), aRows(rRows)
+    {}
+
+    void setDataToDoc(ScDocument* pDoc) const
+    {
+        aCols.setDataToDoc(pDoc, true);
+        aRows.setDataToDoc(pDoc, false);
+    }
+
+    void parseTest(const OString& rJSON) const
+    {
+        // Assumes all flags passed to getSheetGeometryData() are true.
+        boost::property_tree::ptree aTree;
+        std::stringstream aStream(rJSON.getStr());
+        boost::property_tree::read_json(aStream, aTree);
+
+        CPPUNIT_ASSERT_EQUAL(OString(".uno:SheetGeometryData"), OString(aTree.get<std::string>("commandName").c_str()));
+
+        aCols.testPropertyTree(aTree.get_child("columns"), true);
+        aRows.testPropertyTree(aTree.get_child("rows"), false);
+    }
+};
+
+// getSheetGeometryData() should return the exact same message
+// irrespective of client zoom and view-area. Switching views
+// should also not alter it.
+void ScTiledRenderingTest::testSheetGeometryDataInvariance()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    ScModelObj* pModelObj = createDoc("empty.ods");
+    const SheetGeometryData aSGData(
+        // cols
+        {
+            // width spans
+            {
+                { STD_COL_WIDTH,   20     },
+                { 2*STD_COL_WIDTH, 26     },
+                { STD_COL_WIDTH,   MAXCOL }
+            },
+
+            // hidden spans
+            {
+                { 0, 5      },
+                { 1, 12     },
+                { 0, MAXCOL }
+            },
+
+            // filtered spans
+            {
+                { 0, 50     },
+                { 1, 59     },
+                { 0, MAXCOL }
+            }
+        },
+
+        // rows
+        {
+            // height spans
+            {
+                { 300,  50     },
+                { 600,  65     },
+                { 300,  MAXROW }
+            },
+
+            // hidden spans
+            {
+                { 1, 100    },
+                { 0, 500    },
+                { 1, 578    },
+                { 0, MAXROW }
+            },
+
+            // filtered spans
+            {
+                { 0, 150    },
+                { 1, 159    },
+                { 0, MAXROW }
+            }
+        }
+    );
+
+    ScDocument* pDoc = pModelObj->GetDocument();
+
+    ScViewData* pViewData = ScDocShell::GetViewData();
+    CPPUNIT_ASSERT(pViewData);
+
+    // view #1
+    ViewCallback aView1;
+    int nView1 = SfxLokHelper::getView();
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+
+    // view #2
+    SfxLokHelper::createView();
+    int nView2 = SfxLokHelper::getView();
+    ViewCallback aView2;
+    pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2);
+
+    // Try with the default empty document once (nIdx = 0) and then with sheet geometry settings (nIdx = 1)
+    for (size_t nIdx = 0; nIdx < 2; ++nIdx)
+    {
+        if (nIdx)
+            aSGData.setDataToDoc(pDoc);
+
+        SfxLokHelper::setView(nView1);
+        OString aGeomStr1 = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+                /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+
+        SfxLokHelper::setView(nView2);
+        pModelObj->setClientVisibleArea(tools::Rectangle(0, 0, 22474, 47333));
+        pModelObj->setClientZoom(256, 256, 6636, 6636);
+        OString aGeomStr2 = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+                /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+
+        // Check vs. view #1
+        SfxLokHelper::setView(nView1);
+        OString aGeomStr1_2 = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+                /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+        CPPUNIT_ASSERT_EQUAL(aGeomStr1, aGeomStr1_2);
+
+        // Check vs. view #2
+        SfxLokHelper::setView(nView2);
+        OString aGeomStr2_2 = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+                /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+        CPPUNIT_ASSERT_EQUAL(aGeomStr2, aGeomStr2_2);
+    }
+
+    SfxLokHelper::setView(nView1);
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
+    SfxLokHelper::setView(nView2);
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
+}
+
+void ScTiledRenderingTest::testSheetGeometryDataCorrectness()
+{
+    comphelper::LibreOfficeKit::setActive();
+
+    ScModelObj* pModelObj = createDoc("empty.ods");
+    const SheetGeometryData aSGData(
+        // cols
+        {
+            // width spans
+            {
+                { STD_COL_WIDTH,   20     },
+                { 2*STD_COL_WIDTH, 26     },
+                { STD_COL_WIDTH,   MAXCOL }
+            },
+
+            // hidden spans
+            {
+                { 0, 5      },
+                { 1, 12     },
+                { 0, MAXCOL }
+            },
+
+            // filtered spans
+            {
+                { 0, 50     },
+                { 1, 59     },
+                { 0, MAXCOL }
+            }
+        },
+
+        // rows
+        {
+            // height spans
+            {
+                { 300,  50     },
+                { 600,  65     },
+                { 300,  MAXROW }
+            },
+
+            // hidden spans
+            {
+                { 1, 100    },
+                { 0, 500    },
+                { 1, 578    },
+                { 0, MAXROW }
+            },
+
+            // filtered spans
+            {
+                { 0, 150    },
+                { 1, 159    },
+                { 0, MAXROW }
+            }
+        }
+    );
+
+    ScDocument* pDoc = pModelObj->GetDocument();
+
+    ScViewData* pViewData = ScDocShell::GetViewData();
+    CPPUNIT_ASSERT(pViewData);
+
+    // view #1
+    ViewCallback aView1;
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1);
+
+    // with the default empty sheet and test the JSON encoding.
+    OString aGeomDefaultStr = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+            /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+    SheetGeometryData().parseTest(aGeomDefaultStr);
+
+    // Apply geometry settings to the sheet and then test the resulting JSON encoding.
+    aSGData.setDataToDoc(pDoc);
+    OString aGeomStr = pModelObj->getSheetGeometryData(/*bColumns*/ true, /*bRows*/ true, /*bSizes*/ true,
+            /*bHidden*/ true, /*bFiltered*/ true, /*bGroups*/ true);
+    aSGData.parseTest(aGeomStr);
+
+    SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr);
+}
+
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(ScTiledRenderingTest);
commit cced75dfbb8d48e855e3c110807d3c95393e94b1
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue May 5 01:55:37 2020 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Mon May 25 00:39:51 2020 +0530

    Introduce ITiledRenderable::getSheetGeometryData()
    
    ITiledRenderable::getSheetGeometryData(bool bColumns, bool bRows,
                                           bool bSizes, bool bHidden,
                                           bool bFiltered, bool bGroups)
    
    and implement it for the Calc derivation (ScModelObj).
    
    The aim is to use it actively in LOOL instead of the interface:
    
    ITiledRenderable::getRowColumnHeaders(const tools::Rectangle& /*rRectangle*/)
    
    This is used by the LOOL to fetch the sheet geometry data for just the
    current view-area in the clients, so LOOL queries this everytime some
    client's view-area changes.
    
    Like the existing interface, the new one will provide all 'kinds' of
    sheet geometry info [col/row sizes(twips), hidden/filtered and
    grouping]. But the difference is, it generates data for the whole sheet
    (not view-area specific). So the method need not be queried every time
    the view area changes in the LOOL clients, and more importantly it
    enables the clients to locate any cell at any zoom level without any
    further help from the core. This means core needn't send various
    client(zoom) specific positioning messages in pixel aligned twips. It
    just can send all positioning messages in print twips uniformly to all
    clients.
    
    Change-Id: Ib6aee9a0c92746b1576ed244e98cb54b572778c0

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 373deb3c7c53..44f28454c8f8 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -4708,6 +4708,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
 
     OString aCommand(pCommand);
     static const OString aViewRowColumnHeaders(".uno:ViewRowColumnHeaders");
+    static const OString aSheetGeometryData(".uno:SheetGeometryData");
     static const OString aCellCursor(".uno:CellCursor");
     static const OString aFontSubset(".uno:FontSubset&name=");
 
@@ -4805,6 +4806,72 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
         else
             return convertOUString(aHeaders);
     }
+    else if (aCommand.startsWith(aSheetGeometryData))
+    {
+        ITiledRenderable* pDoc = getTiledRenderable(pThis);
+        if (!pDoc)
+        {
+            SetLastExceptionMsg("Document doesn't support tiled rendering");
+            return nullptr;
+        }
+
+        bool bColumns = true;
+        bool bRows = true;
+        bool bSizes = true;
+        bool bHidden = true;
+        bool bFiltered = true;
+        bool bGroups = true;
+        if (aCommand.getLength() > aSheetGeometryData.getLength())
+        {
+            bColumns = bRows = bSizes = bHidden = bFiltered = bGroups = false;
+
+            OString aArguments = aCommand.copy(aSheetGeometryData.getLength() + 1);
+            sal_Int32 nParamIndex = 0;
+            do
+            {
+                OString aParamToken = aArguments.getToken(0, '&', nParamIndex);
+                sal_Int32 nIndex = 0;
+                OString aKey;
+                OString aValue;
+                do
+                {
+                    OString aToken = aParamToken.getToken(0, '=', nIndex);
+                    if (!aKey.getLength())
+                        aKey = aToken;
+                    else
+                        aValue = aToken;
+
+                } while (nIndex >= 0);
+
+                bool bEnableFlag = aValue.isEmpty() ||
+                    aValue.equalsIgnoreAsciiCase("true") || aValue.toInt32() > 0;
+                if (!bEnableFlag)
+                    continue;
+
+                if (aKey == "columns")
+                    bColumns = true;
+                else if (aKey == "rows")
+                    bRows = true;
+                else if (aKey == "sizes")
+                    bSizes = true;
+                else if (aKey == "hidden")
+                    bHidden = true;
+                else if (aKey == "filtered")
+                    bFiltered = true;
+                else if (aKey == "groups")
+                    bGroups = true;
+
+            } while (nParamIndex >= 0);
+        }
+
+        OString aGeomDataStr
+            = pDoc->getSheetGeometryData(bColumns, bRows, bSizes, bHidden, bFiltered, bGroups);
+
+        if (aGeomDataStr.isEmpty())
+            return nullptr;
+
+        return convertOString(aGeomDataStr);
+    }
     else if (aCommand.startsWith(aCellCursor))
     {
         ITiledRenderable* pDoc = getTiledRenderable(pThis);
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index 9e995216e573..2c716098630c 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -177,6 +177,31 @@ public:
         return OUString();
     }
 
+    /**
+     * Generates a serialization of the active (Calc document) sheet's geometry data.
+     *
+     * @param bColumns - if true, the column widths/hidden/filtered/groups data
+     *     are included depending on the settings of the flags bSizes, bHidden,
+     *     bFiltered and bGroups.
+     * @param bRows - if true, the row heights/hidden/filtered/groups data
+     *     are included depending on the settings of the flags bSizes, bHidden,
+     *     bFiltered and bGroups.
+     * @bSizes - if true, the column-widths and/or row-heights data (represented as a list of spans)
+     *     are included depending on the settings of the flags bColumns and bRows.
+     * @bHidden - if true, the hidden columns and/or rows data (represented as a list of spans)
+     *     are included depending on the settings of the flags bColumns and bRows.
+     * @bFiltered - if true, the filtered columns and/or rows data (represented as a list of spans)
+     *     are included depending on the settings of the flags bColumns and bRows.
+     * @bGroups - if true, the column grouping and/or row grouping data
+     *     are included depending on the settings of the flags bColumns and bRows.
+     * @return serialization of the active sheet's geometry data as OString.
+     */
+    virtual OString getSheetGeometryData(bool /*bColumns*/, bool /*bRows*/, bool /*bSizes*/,
+                                         bool /*bHidden*/, bool /*bFiltered*/, bool /*bGroups*/)
+    {
+        return "";
+    }
+
     /**
      * Get position and size of cell cursor in Calc - as JSON in the
      * current' views' co-ordinate system.
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 6e277f10a284..2376e3fdad4d 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -260,6 +260,15 @@ enum RangeNameScope
     SHEET                      // with two scope on Manage Names dialog.
 };
 
+/// Represents the type of sheet geometry data.
+enum class SheetGeomType
+{
+    SIZES,                     // Column widths or row heights.
+    HIDDEN,                    // Hidden columns/rows.
+    FILTERED,                  // Filtered columns/rows.
+    GROUPS                     // Grouping of columns/rows.
+};
+
 struct ScDocStat
 {
     OUString  aDocName;
@@ -2512,6 +2521,16 @@ public:
     bool IsInDocShellRecalc() const   { return mbDocShellRecalc; }
     void SetDocShellRecalc(bool bSet) { mbDocShellRecalc = bSet; }
 
+    /**
+     * Serializes the specified sheet's geometry data.
+     *
+     * @param nTab is the index of the sheet to operate on.
+     * @param bColumns - if true it dumps the data for columns, else it does for rows.
+     * @param eGeomType indicates the type of data to be dumped for rows/columns.
+     * @return the serialization of the specified sheet's geometry data as an OString.
+     */
+    OString dumpSheetGeomData(SCTAB nTab, bool bColumns, SheetGeomType eGeomType);
+
 private:
 
     /**
diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx
index 7c9c87a4f109..329571dfc056 100644
--- a/sc/inc/docuno.hxx
+++ b/sc/inc/docuno.hxx
@@ -368,6 +368,10 @@ public:
     /// @see vcl::ITiledRenderable::getRowColumnHeaders().
     virtual OUString getRowColumnHeaders(const tools::Rectangle& rRectangle) override;
 
+    /// @see vcl::ITiledRenderable::getSheetGeometryData().
+    virtual OString getSheetGeometryData(bool bColumns, bool bRows, bool bSizes, bool bHidden,
+                                         bool bFiltered, bool bGroups) override;
+
     /// @see vcl::ITiledRenderable::getCellCursor().
     virtual OString getCellCursor() override;
 
diff --git a/sc/inc/olinetab.hxx b/sc/inc/olinetab.hxx
index a25064d86c4e..cdaa74d19a93 100644
--- a/sc/inc/olinetab.hxx
+++ b/sc/inc/olinetab.hxx
@@ -59,6 +59,8 @@ public:
     void                    SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize );
     void                    SetHidden( bool bNewHidden );
     void                    SetVisible( bool bNewVisible );
+
+    OString                 dumpAsString() const;
 };
 
 class ScOutlineCollection
@@ -83,6 +85,8 @@ public:
     bool empty() const;
 
     iterator FindStart(SCCOLROW nMinStart);
+
+    OString dumpAsString() const;
 };
 
 class SC_DLLPUBLIC ScOutlineArray
@@ -138,6 +142,8 @@ public:
     void finalizeImport(const ScTable& rTable);
 
     void RemoveAll();
+
+    OString dumpAsString() const;
 };
 
 class ScOutlineTable
diff --git a/sc/inc/segmenttree.hxx b/sc/inc/segmenttree.hxx
index 9d772a0b4b46..f37a3d3facd6 100644
--- a/sc/inc/segmenttree.hxx
+++ b/sc/inc/segmenttree.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_SC_INC_SEGMENTTREE_HXX
 
 #include "types.hxx"
+#include <rtl/string.hxx>
 
 #include <memory>
 
@@ -76,6 +77,8 @@ public:
 
     SCROW findLastTrue() const;
 
+    OString dumpAsString();
+
 private:
     ::std::unique_ptr<ScFlatBoolSegmentsImpl> mpImpl;
 };
@@ -99,6 +102,8 @@ public:
     void removeSegment(SCCOL nCol1, SCCOL nCol2);
     void insertSegment(SCCOL nCol, SCCOL nSize);
 
+    OString dumpAsString();
+
 private:
     ::std::unique_ptr<ScFlatBoolSegmentsImpl> mpImpl;
 };
@@ -147,6 +152,8 @@ public:
 
     void enableTreeSearch(bool bEnable);
 
+    OString dumpAsString();
+
 private:
     ::std::unique_ptr<ScFlatUInt16SegmentsImpl> mpImpl;
 };
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 12f8bb87bc89..5ffd70c77541 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -1081,6 +1081,15 @@ public:
     SCCOL ClampToAllocatedColumns(SCCOL nCol) const { return std::min(nCol, static_cast<SCCOL>(aCol.size() - 1)); }
     SCCOL GetAllocatedColumnsCount() const { return aCol.size(); }
 
+    /**
+     * Serializes the sheet's geometry data.
+     *
+     * @param bColumns - if true it dumps the data for columns, else it does for rows.
+     * @param eGeomType indicates the type of data to be dumped for rows/columns.

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list