compilerplugins/clang/badstatics.cxx         |    3 
 editeng/source/editeng/editview.cxx          |    4 
 include/sfx2/lokhelper.hxx                   |   18 +
 sc/qa/unit/tiledrendering/tiledrendering.cxx |    3 
 sc/source/ui/unoobj/docuno.cxx               |    7 
 sc/source/ui/view/gridwin4.cxx               |  475 ++++++++++-----------------
 sc/source/ui/view/tabview.cxx                |   10 
 sc/source/ui/view/tabview3.cxx               |   13 
 sc/source/ui/view/viewdata.cxx               |    2 
 sfx2/source/view/lokhelper.cxx               |   78 ++++
 10 files changed, 324 insertions(+), 289 deletions(-)

New commits:
commit bdd0579b58f7a3b8c1886ea8513618c647c0ad30
Author:     Marco Cecchetti <marco.cecche...@collabora.com>
AuthorDate: Mon Jan 22 16:43:11 2024 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Feb 8 17:11:39 2024 +0100

    lok: calc: GridWindow size not updated for some view
    
    The grid window size was updated for the view used for painting and
    not for other views with the same zoom level. In fact the grid window
    size was updated in ScModelObj::paintTile only. Now the required
    updating is performed in lcl_ExtendTiledDimension and
    ScTabView::SetCursor, too.
    In order to get this working it has been neede to revert changes in
    `ScModelObj::setClientVisibleArea` introduced by
    https://gerrit.libreoffice.org/c/core/+/161907
    
    Change-Id: Ie8f585b861b0c916624d8e2f9d828cf23b799672
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162406
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Szymon Kłos <szymon.k...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162558
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx 
b/sc/qa/unit/tiledrendering/tiledrendering.cxx
index 14b80dde4ca7..85f9c235f450 100644
--- a/sc/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx
@@ -3603,6 +3603,9 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, 
testLongFirstColumnMouseClick)
     // very long (longer than ~800px default size of GridWindow) triggers a 
code-path where the cell
     // selected is the neighbouring cell even when we clicked on the area of 
the first cell.
 
+    comphelper::LibreOfficeKit::setCompatFlag(
+        comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
+
     ScModelObj* pModelObj = createDoc("DocumentWithLongFirstColumn.ods");
     CPPUNIT_ASSERT(pModelObj);
     
pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 96c4d18f69d7..f92864e76ece 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -1171,13 +1171,6 @@ void ScModelObj::setClientVisibleArea(const 
tools::Rectangle& rRectangle)
         if (pTabView)
             pTabView->extendTiledAreaIfNeeded();
     }
-
-    // Set the GridWindow size to the client area size, so that the logic in 
GridWindow works correctly
-    // for the current view and doesn't cause any unexpected behaviour related 
to window size and checks if we are
-    // outside of the window.
-
-    ScGridWindow* pGridWindow = pViewData->GetActiveWin();
-    pGridWindow->SetOutputSizePixel(Size(rRectangle.GetWidth() * 
pViewData->GetPPTX(), rRectangle.GetHeight() * pViewData->GetPPTY()));
 }
 
 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 a865acb71505..5d0699f26e6b 100644
--- a/sc/source/ui/view/tabview.cxx
+++ b/sc/source/ui/view/tabview.cxx
@@ -2734,6 +2734,16 @@ void lcl_ExtendTiledDimension(bool bColumn, const 
SCCOLROW nEnd, const SCCOLROW
     if (!pDocSh)
         return;
 
+    if (pModelObj)
+    {
+        ScGridWindow* pGridWindow = rViewData.GetActiveWin();
+        if (pGridWindow)
+        {
+            Size aNewSizePx(aNewSize.Width() * rViewData.GetPPTX(), 
aNewSize.Height() * rViewData.GetPPTY());
+            pGridWindow->SetOutputSizePixel(aNewSizePx);
+        }
+    }
+
     // New area extended to the right/bottom of the sheet after last col/row
     tools::Rectangle aNewArea(Point(0, 0), aNewSize);
     // excluding overlapping area with aNewArea
diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx
index 7de940ce24a9..fb91cc886ef3 100644
--- a/sc/source/ui/view/tabview3.cxx
+++ b/sc/source/ui/view/tabview3.cxx
@@ -423,9 +423,22 @@ void ScTabView::SetCursor( SCCOL nPosX, SCROW nPosY, bool 
bNew )
     if (pModelObj)
         aNewSize = pModelObj->getDocumentSize();
 
+    if (aOldSize == aNewSize)
+        return;
+
     if (!pDocSh)
         return;
 
+    if (pModelObj)
+    {
+        ScGridWindow* pGridWindow = aViewData.GetActiveWin();
+        if (pGridWindow)
+        {
+            Size aNewSizePx(aNewSize.Width() * aViewData.GetPPTX(), 
aNewSize.Height() * aViewData.GetPPTY());
+            pGridWindow->SetOutputSizePixel(aNewSizePx);
+        }
+    }
+
     // 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());
commit f840a0d54d873d3003f8b624a50557f8c9872477
Author:     Marco Cecchetti <marco.cecche...@collabora.com>
AuthorDate: Wed Dec 13 17:50:44 2023 +0100
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Thu Feb 8 17:11:32 2024 +0100

    lok: calc: fix for rendering issues on in place editing
    
    Our main problem is how to compute the correct output area for the
    requested tile zoom level. The old solution was using a fine-tuned
    edit rectangle as output area. An edit rectangle is the rectangle
    computed according to the range of rows and columns involved in the
    text editing. Unfortunately in some cases the edit rectangle can be
    enough larger than the output area. For instance that occurs with
    centered text.
    The new proposed solution is able to scale the output area to the
    requested tile zoom level by a few pixels (0 up to 3) offset/size
    error. The hope is to reduce the error in some follow-up patch.
    
    The new solution is also able to perform painting of text edited by
    different views in the correct order. The last painted text is the one
    belonging to the last view where editing occurred.
    SfxViewShell::maEditViewHistory keeps track of the last 10 editing
    events per document.
    
    Change-Id: I8f1035a730cb2b94b0990f3c8eb6445511b94223
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162196
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163031
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/compilerplugins/clang/badstatics.cxx 
b/compilerplugins/clang/badstatics.cxx
index 18638695bbeb..1d003acdb8a6 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -233,6 +233,9 @@ public:
                    // AquaA11yFocusTracker::m_aDocumentWindowList elements 
symmetrically added and
                    // removed in AquaA11yFocusTracker::window_got_focus and
                    // AquaA11yFocusTracker::WindowEventHandler (TODO: is that 
guaranteed?)
+                || (loplugin::DeclCheck(pVarDecl).Var("maEditViewHistory")
+                        .Class("LOKEditViewHistory").GlobalNamespace())
+                   // sfx2/lokhelper.hxx, only handling pointers, not owning
                ) // these variables appear unproblematic
             {
                 return true;
diff --git a/editeng/source/editeng/editview.cxx 
b/editeng/source/editeng/editview.cxx
index e08c3c81d77d..9868c3ebec59 100644
--- a/editeng/source/editeng/editview.cxx
+++ b/editeng/source/editeng/editview.cxx
@@ -60,6 +60,7 @@
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/lok.hxx>
 #include <sfx2/viewsh.hxx>
+#include <sfx2/lokhelper.hxx>
 #include <osl/diagnose.h>
 #include <boost/property_tree/json_parser.hpp>
 
@@ -208,6 +209,7 @@ tools::Rectangle lcl_negateRectX(const tools::Rectangle& 
rRect)
 
 void EditView::InvalidateWindow(const tools::Rectangle& rClipRect)
 {
+    LOKEditViewHistory::Update();
     bool bNegativeX = IsNegativeX();
     if (EditViewCallbacks* pEditViewCallbacks = 
getImpl().getEditViewCallbacks())
     {
@@ -243,6 +245,8 @@ void EditView::InvalidateOtherViewWindows( const 
tools::Rectangle& rInvRect )
 void EditView::Invalidate()
 {
     const tools::Rectangle& rInvRect = GetInvalidateRect();
+
+    LOKEditViewHistory::Update();
     getImpl().InvalidateAtWindow(rInvRect);
     InvalidateOtherViewWindows(rInvRect);
 }
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index f87bbd70cd36..c4e88035fd96 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -23,8 +23,10 @@
 #include <cstddef>
 #include <rtl/strbuf.hxx>
 #include <rtl/string.hxx>
+#include <list>
 #include <optional>
 #include <string_view>
+#include <unordered_map>
 
 #define LOK_NOTIFY_LOG_TO_CLIENT 1
 
@@ -261,6 +263,22 @@ public:
     ~SfxLokLanguageGuard();
 };
 
+typedef std::list<SfxViewShell*> ViewShellList;
+
+/// Used to keep track of the last N views that text edited a document through 
an EditView
+class SFX2_DLLPUBLIC LOKEditViewHistory
+{
+public:
+    typedef std::list<SfxViewShell*> ViewShellList;
+    typedef std::unordered_map<int, ViewShellList> EditViewHistoryMap;
+
+    static void Update(bool bRemove = false);
+    static ViewShellList GetHistoryForDoc(ViewShellDocId aDocId);
+    static ViewShellList GetSortedViewsForDoc(ViewShellDocId aDocId);
+private:
+    static EditViewHistoryMap maEditViewHistory;
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 344d99b26cef..e9be15580668 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -280,26 +280,6 @@ static void lcl_DrawHighlight( ScOutputData& rOutputData, 
const ScViewData& rVie
     }
 }
 
-// Calculates top-left offset to be applied based on margins and indent.
-static void lcl_GetEditAreaTLOffset(tools::Long& nOffsetX, tools::Long& 
nOffsetY, const ScAddress& rAddr,
-                                    const ScViewData& rViewData, ScDocument& 
rDoc)
-{
-    tools::Long nLeftMargin = 0;
-    tools::Long nTopMargin = 0;
-    tools::Long nIndent = 0;
-    tools::Long nDummy = 0;
-    ScEditUtil aEUtil(&rDoc, rAddr.Col(), rAddr.Row(), rAddr.Tab(),
-        Point(0, 0), nullptr, rViewData.GetPPTX(),
-        rViewData.GetPPTY(), Fraction(1.0), Fraction(1.0),
-        false /* bPrintTwips */);
-    const ScPatternAttr* pPattern = rDoc.GetPattern(rAddr);
-    if (!rDoc.IsLayoutRTL(rAddr.Tab()))
-        nIndent = aEUtil.GetIndent(pPattern);
-    aEUtil.GetMargins(pPattern, nLeftMargin, nTopMargin, nDummy, nDummy);
-    nOffsetX = nIndent + nLeftMargin;
-    nOffsetY = nTopMargin;
-}
-
 void ScGridWindow::DoInvertRect( const tools::Rectangle& rPixel )
 {
     if ( rPixel == aInvertRect )
@@ -656,24 +636,27 @@ private:
 
 namespace
 {
-int lcl_GetMultiLineHeight(EditEngine& rEditEngine)
+tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect)
 {
-    int nHeight = 0;
-    int nParagraphs = rEditEngine.GetParagraphCount();
-    if (nParagraphs > 1 || (nParagraphs > 0 && rEditEngine.GetLineCount(0) > 
1))
-    {
-        for (int nPara = 0; nPara < nParagraphs; nPara++)
-        {
-            nHeight += rEditEngine.GetLineCount(nPara) * 
rEditEngine.GetLineHeight(nPara);
-        }
-    }
+    return {-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()};
+}
 
-    return nHeight;
+tools::Long GetSide(const tools::Rectangle& rRect, int i)
+{
+    static decltype(&tools::Rectangle::Left) GetSides[4] = {
+        &tools::Rectangle::Left, &tools::Rectangle::Top,
+        &tools::Rectangle::Right, &tools::Rectangle::Bottom
+    };
+    return (rRect.*GetSides[i])();
 }
 
-tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect)
+Fraction GetZoom(const ScViewData& rViewData, int i)
 {
-    return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), 
rRect.Bottom());
+    static decltype(&ScViewData::GetZoomX) GetZooms[4] = {
+        &ScViewData::GetZoomX, &ScViewData::GetZoomY,
+        &ScViewData::GetZoomX, &ScViewData::GetZoomY
+    };
+    return (rViewData.*GetZooms[i])();
 }
 }
 
@@ -1095,183 +1078,195 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
         }
     }
 
-    // paint in-place editing
+    // in place editing - lok case
     if (bIsTiledRendering)
     {
         ScTabViewShell* pThisViewShell = mrViewData.GetViewShell();
-        SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+        ViewShellList aCurrentDocViewList = 
LOKEditViewHistory::GetSortedViewsForDoc(pThisViewShell->GetDocId());
+        tools::Rectangle aTileRectPx(Point(nScrX, nScrY), 
Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
 
-        while (pViewShell)
+        for (SfxViewShell* pVS: aCurrentDocViewList)
         {
-            bool bEnterLoop = bIsTiledRendering || pViewShell != 
pThisViewShell;
-            if (bEnterLoop && pViewShell->GetDocId() == 
pThisViewShell->GetDocId())
+            auto pTabViewShell = dynamic_cast<ScTabViewShell*>(pVS);
+            if (!pTabViewShell)
+                continue;
+
+            ScViewData& rOtherViewData = pTabViewShell->GetViewData();
+            ScSplitPos eOtherWhich = rOtherViewData.GetEditActivePart();
+
+            bool bOtherEditMode = rOtherViewData.HasEditView(eOtherWhich);
+            SCCOL nCol1 = rOtherViewData.GetEditStartCol();
+            SCROW nRow1 = rOtherViewData.GetEditStartRow();
+            SCCOL nCol2 = rOtherViewData.GetEditEndCol();
+            SCROW nRow2 = rOtherViewData.GetEditEndRow();
+
+            if (!(bOtherEditMode
+                  && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 && nRow1 
<= nY2 )
+                  && rOtherViewData.GetRefTabNo() == nTab))
+                continue; // only views where in place editing is occurring 
need to be rendered
+
+            EditView* pOtherEditView = rOtherViewData.GetEditView(eOtherWhich);
+            if (!pOtherEditView)
+                continue;
+
+            rDevice.SetLineColor();
+            // Theme colors
+            const ScPatternAttr* pPattern = rDoc.GetPattern( nCol1, nRow1, 
nTab );
+            Color aCellColor = pPattern->GetItem(ATTR_BACKGROUND).GetColor();
+            if (aCellColor.IsTransparent())
             {
-                ScTabViewShell* pTabViewShell = 
dynamic_cast<ScTabViewShell*>(pViewShell);
-                if (pTabViewShell)
-                {
-                    ScViewData& rOtherViewData = pTabViewShell->GetViewData();
-                    ScSplitPos eOtherWhich = 
rOtherViewData.GetEditActivePart();
-
-                    bool bOtherEditMode = 
rOtherViewData.HasEditView(eOtherWhich);
-                    SCCOL nCol1 = rOtherViewData.GetEditStartCol();
-                    SCROW nRow1 = rOtherViewData.GetEditStartRow();
-                    SCCOL nCol2 = rOtherViewData.GetEditEndCol();
-                    SCROW nRow2 = rOtherViewData.GetEditEndRow();
-                    bOtherEditMode = bOtherEditMode
-                            && ( nCol2 >= nX1 && nCol1 <= nX2 && nRow2 >= nY1 
&& nRow1 <= nY2 );
-                    if (bOtherEditMode && rOtherViewData.GetRefTabNo() == nTab)
-                    {
-                        EditView* pOtherEditView = 
rOtherViewData.GetEditView(eOtherWhich);
-                        if (pOtherEditView)
-                        {
-                            tools::Long nScreenX = aOutputData.nScrX;
-                            tools::Long nScreenY = aOutputData.nScrY;
+                const ScViewRenderingOptions& rViewRenderingOptions = 
pTabViewShell->GetViewRenderingData();
+                aCellColor = rViewRenderingOptions.GetDocColor();
+            }
+            rDevice.SetFillColor(aCellColor);
+            pOtherEditView->SetBackgroundColor(aCellColor);
+
+            // edit rectangle / background
+            Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eOtherWhich );
+            Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eOtherWhich );
+            tools::Rectangle aEditRectPx(aStart, aEnd);
+            if (bLokRTL)
+            {
+                // Transform the cell range X coordinates such that the edit 
cell area is
+                // horizontally mirrored w.r.t the (combined-)tile.
+                aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X()));
+                aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X()));
+            }
 
-                            rDevice.SetLineColor();
-                            SfxViewShell* pSfxViewShell = 
SfxViewShell::Current();
-                            ScTabViewShell* pCurrentViewShell = 
dynamic_cast<ScTabViewShell*>(pSfxViewShell);
-                            if (pCurrentViewShell)
-                            {
-                                const ScPatternAttr* pPattern = 
rDoc.GetPattern( nCol1, nRow1, nTab );
-                                Color aCellColor = 
pPattern->GetItem(ATTR_BACKGROUND).GetColor();
-                                if (aCellColor.IsTransparent())
-                                {
-                                    const ScViewRenderingOptions& 
rViewRenderingOptions = pCurrentViewShell->GetViewRenderingData();
-                                    aCellColor = 
rViewRenderingOptions.GetDocColor();
-                                }
-                                rDevice.SetFillColor(aCellColor);
-                                pOtherEditView->SetBackgroundColor(aCellColor);
-                            }
-                            Point aStart = mrViewData.GetScrPos( nCol1, nRow1, 
eOtherWhich );
-                            Point aEnd = mrViewData.GetScrPos( nCol2+1, 
nRow2+1, eOtherWhich );
+            // don't overwrite grid
+            tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
+            aEnd.AdjustX( -(2 * nLayoutSign) );
+            aEnd.AdjustY( -2 );
 
-                            if (bIsTiledRendering)
-                            {
-                                EditEngine& rEditEngine = 
pOtherEditView->getEditEngine();
-                                
aEnd.AdjustY(lcl_GetMultiLineHeight(rEditEngine));
-                            }
+            tools::Rectangle aBackground(aStart, aEnd);
+            if (bLokRTL)
+                aBackground.Normalize();
+            tools::Rectangle aBGAbs(aBackground);
 
-                            if (bLokRTL)
-                            {
-                                // Transform the cell range X coordinates such 
that the edit cell area is
-                                // horizontally mirrored w.r.t the 
(combined-)tile.
-                                
aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X()));
-                                aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X()));
-                            }
+            // Need to draw the background in absolute coords.
+            Point aOriginTw = aOriginalMode.GetOrigin();
+            Point aOriginPx = o3tl::convert(aOriginTw, o3tl::Length::twip, 
o3tl::Length::px);
+            Point aOriginAbsPx = aOriginPx + aTileRectPx.GetPos();
+            aBackground += aOriginAbsPx;
+            rDevice.SetMapMode(aDrawMode);
 
-                            // don't overwrite grid
-                            tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
-                            aEnd.AdjustX( -(2 * nLayoutSign) );
-                            aEnd.AdjustY( -2 );
-
-                            tools::Rectangle aBackground(aStart, aEnd);
-                            if (bLokRTL)
-                                aBackground.Normalize();
-
-                            // Need to draw the background in absolute coords.
-                            Point aOrigin = aOriginalMode.GetOrigin();
-                            aOrigin.setX(
-                                o3tl::convert(aOrigin.getX(), 
o3tl::Length::twip, o3tl::Length::px)
-                                + nScreenX);
-                            aOrigin.setY(
-                                o3tl::convert(aOrigin.getY(), 
o3tl::Length::twip, o3tl::Length::px)
-                                + nScreenY);
-                            aBackground += aOrigin;
-                            rDevice.SetMapMode(aDrawMode);
-
-                            static const double twipFactor = 15 * 1.76388889; 
// 26.45833335
-                            // keep into account the zoom factor
-                            aOrigin = Point((aOrigin.getX() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleX()),
-                                            (aOrigin.getY() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleY()));
-
-                            MapMode aNew = rDevice.GetMapMode();
-                            aNew.SetOrigin(aOrigin);
-                            rDevice.SetMapMode(aNew);
-
-                            // paint the background
-                            
rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
-                            tools::Rectangle aBGAbs(aBackground);
-
-                            tools::Rectangle aEditRect(aBackground);
-                            tools::Long nOffsetX = 0, nOffsetY = 0;
-                            // Get top-left offset because of margin and 
indent.
-                            lcl_GetEditAreaTLOffset(nOffsetX, nOffsetY, 
ScAddress(nCol1, nRow1, nTab), mrViewData, rDoc);
-                            aEditRect.AdjustLeft(nOffsetX + 1);
-                            aEditRect.AdjustRight(1);
-                            aEditRect.AdjustTop(nOffsetY + 1);
-                            aEditRect.AdjustBottom(1);
-
-                            // EditView has an 'output area' which is used to 
clip the 'paint area' we provide below.
-                            // So they need to be in the same 
coordinates/units. This is tied to the mapmode of the gridwin
-                            // attached to the EditView, so we have to change 
its mapmode too (temporarily). We save the
-                            // original mapmode and 'output area' and roll 
them back when we finish painting to rDevice.
-                            OutputDevice& rOtherWin = 
pOtherEditView->GetOutputDevice();
-                            const tools::Rectangle 
aOrigOutputArea(pOtherEditView->GetOutputArea()); // Not in pixels.
-                            const MapMode aOrigMapMode = 
rOtherWin.GetMapMode();
-                            rOtherWin.SetMapMode(rDevice.GetMapMode());
-
-                            // Avoid sending wrong cursor/selection messages 
by the 'other' view, as the output-area is going
-                            // to be tweaked temporarily to match the current 
view's zoom.
-                            SuppressEditViewMessagesGuard 
aGuard(*pOtherEditView);
-                            comphelper::ScopeGuard aOutputGuard(
-                                [pOtherEditView, aOrigOutputArea, bLokRTL] {
-                                    if (bLokRTL && aOrigOutputArea != 
pOtherEditView->GetOutputArea())
-                                        
pOtherEditView->SetOutputArea(aOrigOutputArea);
-                                });
-
-                            aEditRect = rDevice.PixelToLogic(aEditRect);
-                            if (bIsTiledRendering)
-                                pOtherEditView->SetOutputArea(aEditRect);
-                            else
-                                
aEditRect.Intersection(pOtherEditView->GetOutputArea());
-                            pOtherEditView->Paint(aEditRect, &rDevice);
+            // keep into account the zoom factor
+            static const double twipFactor = 15 * 1.76388889; // 26.45833335
+            Point aNewOrigin((aOriginAbsPx.getX() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleX()),
+                             (aOriginAbsPx.getY() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleY()));
 
-                            // EditView will do the cursor notifications 
correctly if we're in
-                            // print-twips messaging mode.
-                            if (bIsTiledRendering && 
!comphelper::LibreOfficeKit::isCompatFlagSet(
-                                    
comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
-                            {
-                                // Now we need to get relative cursor position 
within the editview.
-                                // This is for sending the pixel-aligned twips 
position of the cursor to the specific views with
-                                // the same given zoom level.
-                                tools::Rectangle aCursorRect = 
pOtherEditView->GetEditCursor();
-                                Point aCursPos = 
OutputDevice::LogicToLogic(aCursorRect.TopLeft(),
-                                        MapMode(MapUnit::Map100thMM), 
MapMode(MapUnit::MapTwip));
-
-                                const MapMode& rDevMM = rDevice.GetMapMode();
-                                MapMode aMM(MapUnit::MapTwip);
-                                aMM.SetScaleX(rDevMM.GetScaleX());
-                                aMM.SetScaleY(rDevMM.GetScaleY());
-
-                                aBGAbs.AdjustLeft(1);
-                                aBGAbs.AdjustTop(1);
-                                aCursorRect = 
GetOutDev()->PixelToLogic(aBGAbs, aMM);
-                                aCursorRect.setWidth(0);
-                                aCursorRect.Move(aCursPos.getX(), 0);
-                                // Sends view cursor position to views of all 
matching zooms if needed (avoids duplicates).
-                                InvalidateLOKViewCursor(aCursorRect, 
aMM.GetScaleX(), aMM.GetScaleY());
-                            }
+            MapMode aNewMM = rDevice.GetMapMode();
+            aNewMM.SetOrigin(aNewOrigin);
+            rDevice.SetMapMode(aNewMM);
 
-                            // Rollback the mapmode and 'output area'.
-                            rOtherWin.SetMapMode(aOrigMapMode);
-                            if (!bIsTiledRendering)
-                                pOtherEditView->SetOutputArea(aOrigOutputArea);
-                            rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
-                        }
-                    }
+            // paint the background
+            rDevice.DrawRect(rDevice.PixelToLogic(aBackground));
+
+            // paint text
+            const tools::Rectangle 
aOrigOutputAreaTw(pOtherEditView->GetOutputArea()); // Not in pixels.
+
+            tools::Rectangle aNewOutputArea;
+            // compute output area for view with a different zoom level wrt 
the view used for painting
+            if (!(mrViewData.GetZoomX() == rOtherViewData.GetZoomX() &&
+                  mrViewData.GetZoomY() == rOtherViewData.GetZoomY()))
+            {
+                Point aOtherStart = rOtherViewData.GetScrPos( nCol1, nRow1, 
eOtherWhich );
+                Point aOtherEnd = rOtherViewData.GetScrPos( nCol2+1, nRow2+1, 
eOtherWhich );
+                tools::Rectangle aOtherEditRectPx(aOtherStart, aOtherEnd);
+
+                tools::Long sides[4];
+                for (auto i: {0, 1, 2, 3})
+                {
+                    sides[i] = static_cast<tools::Long>(
+                        GetSide(aEditRectPx, i)
+                        + double(::GetZoom(mrViewData, i) / 
::GetZoom(rOtherViewData, i))
+                              * (double(::GetZoom(rOtherViewData, i)) * 
GetSide(aOrigOutputAreaTw, i)
+                                 - GetSide(aOtherEditRectPx, i) * twipFactor)
+                              / twipFactor);
+                }
+
+                aNewOutputArea = tools::Rectangle(sides[0], sides[1], 
sides[2], sides[3]);
+                aNewOutputArea += aOriginAbsPx;
+            }
+            // compute output area for RTL case
+            if (bLokRTL)
+            {
+                if (aNewOutputArea.IsEmpty())
+                {
+                    // same zoom level as view used for painting
+                    aNewOutputArea = rDevice.LogicToPixel(aOrigOutputAreaTw);
                 }
+                // Transform the cell range X coordinates such that the edit 
cell area is
+                // horizontally mirrored w.r.t the (combined-)tile.
+                aNewOutputArea = tools::Rectangle(
+                    pLokRTLCtxt->docToTilePos(aNewOutputArea.Left() - 
aOriginAbsPx.X()) + aOriginAbsPx.X(),
+                    aNewOutputArea.Top(),
+                    pLokRTLCtxt->docToTilePos(aNewOutputArea.Right() - 
aOriginAbsPx.X()) + aOriginAbsPx.X(),
+                    aNewOutputArea.Bottom());
+                aNewOutputArea.Normalize();
             }
 
-            pViewShell = SfxViewShell::GetNext(*pViewShell);
-        }
+            if (aNewOutputArea.IsEmpty())
+            {
+                // same zoom level and not RTL: no need to change the output 
area before painting
+                pOtherEditView->Paint(rDevice.PixelToLogic(aTileRectPx), 
&rDevice);
+            }
+            else
+            {
+                // EditView has an 'output area' which is used to clip the 
'paint area' we provide below.
+                // So they need to be in the same coordinates/units. This is 
tied to the mapmode of the gridwin
+                // attached to the EditView, so we have to change its mapmode 
too (temporarily). We save the
+                // original mapmode and 'output area' and roll them back when 
we finish painting to rDevice.
+                OutputDevice& rOtherWin = pOtherEditView->GetOutputDevice();
+                const MapMode aOrigMapMode = rOtherWin.GetMapMode();
+                rOtherWin.SetMapMode(rDevice.GetMapMode());
+
+                // Avoid sending wrong cursor/selection messages by the 
'other' view, as the output-area is going
+                // to be tweaked temporarily to match the current view's zoom.
+                SuppressEditViewMessagesGuard aGuard(*pOtherEditView);
+
+                
pOtherEditView->SetOutputArea(rDevice.PixelToLogic(aNewOutputArea));
+                pOtherEditView->Paint(rDevice.PixelToLogic(aTileRectPx), 
&rDevice);
+
+                // EditView will do the cursor notifications correctly if 
we're in
+                // print-twips messaging mode.
+                if (pTabViewShell == pThisViewShell
+                    && !comphelper::LibreOfficeKit::isCompatFlagSet(
+                        comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
+                {
+                    // Now we need to get relative cursor position within the 
editview.
+                    // This is for sending the pixel-aligned twips position of 
the cursor to the specific views with
+                    // the same given zoom level.
+                    tools::Rectangle aCursorRect = pEditView->GetEditCursor();
+                    Point aCursPos = o3tl::toTwips(aCursorRect.TopLeft(), 
o3tl::Length::mm100);
+
+                    const MapMode& rDevMM = rDevice.GetMapMode();
+                    MapMode aMM(MapUnit::MapTwip);
+                    aMM.SetScaleX(rDevMM.GetScaleX());
+                    aMM.SetScaleY(rDevMM.GetScaleY());
+
+                    aBGAbs.AdjustLeft(1);
+                    aBGAbs.AdjustTop(1);
+                    aCursorRect = GetOutDev()->PixelToLogic(aBGAbs, aMM);
+                    aCursorRect.setWidth(0);
+                    aCursorRect.Move(aCursPos.getX(), 0);
+                    // Sends view cursor position to views of all matching 
zooms if needed (avoids duplicates).
+                    InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), 
aMM.GetScaleY());
+                }
 
+                // Rollback the mapmode and 'output area'.
+                rOtherWin.SetMapMode(aOrigMapMode);
+                pOtherEditView->SetOutputArea(aOrigOutputAreaTw);
+            }
+            rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
+        }
     }
 
     // In-place editing - when the user is typing, we need to paint the text
     // using the editeng.
     // It's being done after EndDrawLayers() to get it outside the overlay
     // buffer and on top of everything.
-    if (bInPlaceEditing)
+    if (bInPlaceEditing && !bIsTiledRendering)
     {
         // get the coordinates of the area we need to clear (overpaint by
         // the background)
@@ -1284,14 +1279,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
         Point aStart = mrViewData.GetScrPos( nCol1, nRow1, eWhich );
         Point aEnd = mrViewData.GetScrPos( nCol2+1, nRow2+1, eWhich );
 
-        if (bLokRTL)
-        {
-            // Transform the cell range X coordinates such that the edit cell 
area is
-            // horizontally mirrored w.r.t the (combined-)tile.
-            aStart.setX(pLokRTLCtxt->docToTilePos(aStart.X()));
-            aEnd.setX(pLokRTLCtxt->docToTilePos(aEnd.X()));
-        }
-
         // don't overwrite grid
         tools::Long nLayoutSign = bLayoutRTL ? -1 : 1;
         aEnd.AdjustX( -(2 * nLayoutSign) );
@@ -1299,96 +1286,20 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, 
const ScTableInfo& rTableI
 
         // set the correct mapmode
         tools::Rectangle aBackground(aStart, aEnd);
-        if (bLokRTL)
-            aBackground.Normalize();
-        tools::Rectangle aBGAbs(aBackground);
 
-        if (bIsTiledRendering)
-        {
-            // Need to draw the background in absolute coords.
-            Point aOrigin = aOriginalMode.GetOrigin();
-            aOrigin.setX(o3tl::convert(aOrigin.getX(), o3tl::Length::twip, 
o3tl::Length::px)
-                         + nScrX);
-            aOrigin.setY(o3tl::convert(aOrigin.getY(), o3tl::Length::twip, 
o3tl::Length::px)
-                         + nScrY);
-            aBackground += aOrigin;
-            rDevice.SetMapMode(aDrawMode);
-        }
-        else
-            rDevice.SetMapMode(mrViewData.GetLogicMode());
+        // paint the background
+        rDevice.SetMapMode(mrViewData.GetLogicMode());
 
-        if (bIsTiledRendering)
-        {
-            Point aOrigin = aOriginalMode.GetOrigin();
-            aOrigin.setX(o3tl::convert(aOrigin.getX(), o3tl::Length::twip, 
o3tl::Length::px)
-                         + nScrX);
-            aOrigin.setY(o3tl::convert(aOrigin.getY(), o3tl::Length::twip, 
o3tl::Length::px)
-                         + nScrY);
-            static const double twipFactor = 15 * 1.76388889; // 26.45833335
-            // keep into account the zoom factor
-            aOrigin = Point((aOrigin.getX() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleX()),
-                            (aOrigin.getY() * twipFactor) / 
static_cast<double>(aDrawMode.GetScaleY()));
-            MapMode aNew = rDevice.GetMapMode();
-            aNew.SetOrigin(aOrigin);
-            rDevice.SetMapMode(aNew);
-        }
+        tools::Rectangle aLogicRect(rDevice.PixelToLogic(aBackground));
+        //tdf#100925, rhbz#1283420, Draw some text here, to get
+        //X11CairoTextRender::getCairoContext called, so that the forced read
+        //from the underlying X Drawable gets it to sync.
+        rDevice.DrawText(aLogicRect.BottomLeft(), " ");
+        rDevice.DrawRect(aLogicRect);
 
         // paint the editeng text
-        if (bIsTiledRendering)
-        {
-            // EditView has an 'output area' which is used to clip the paint 
area we provide below.
-            // So they need to be in the same coordinates/units. This is tied 
to the mapmode of the gridwin
-            // attached to the EditView, so we have to change its mapmode too 
(temporarily). We save the
-            // original mapmode and 'output area' and roll them back when we 
finish painting to rDevice.
-            const MapMode aOrigMapMode = GetMapMode();
-            SetMapMode(rDevice.GetMapMode());
-
-            // Avoid sending wrong cursor/selection messages by the current 
view, as the output-area is going
-            // to be tweaked temporarily to match other view's zoom. (This 
does not affect the manual
-            // cursor-messaging done in the non print-twips mode)
-            SuppressEditViewMessagesGuard aGuard(*pEditView);
-
-            // EditView will do the cursor notifications correctly if we're in
-            // print-twips messaging mode.
-            if (!comphelper::LibreOfficeKit::isCompatFlagSet(
-                    comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs))
-            {
-                // Now we need to get relative cursor position within the 
editview.
-                // This is for sending the pixel-aligned twips position of the 
cursor to the specific views with
-                // the same given zoom level.
-                tools::Rectangle aCursorRect = pEditView->GetEditCursor();
-                Point aCursPos = o3tl::toTwips(aCursorRect.TopLeft(), 
o3tl::Length::mm100);
-
-                const MapMode& rDevMM = rDevice.GetMapMode();
-                MapMode aMM(MapUnit::MapTwip);
-                aMM.SetScaleX(rDevMM.GetScaleX());
-                aMM.SetScaleY(rDevMM.GetScaleY());
-
-                aBGAbs.AdjustLeft(1);
-                aBGAbs.AdjustTop(1);
-                aCursorRect = GetOutDev()->PixelToLogic(aBGAbs, aMM);
-                aCursorRect.setWidth(0);
-                aCursorRect.Move(aCursPos.getX(), 0);
-                // Sends view cursor position to views of all matching zooms 
if needed (avoids duplicates).
-                InvalidateLOKViewCursor(aCursorRect, aMM.GetScaleX(), 
aMM.GetScaleY());
-            }
-
-            // Rollback the mapmode and 'output area'.
-            SetMapMode(aOrigMapMode);
-        }
-        else
-        {
-            // paint the background
-            tools::Rectangle aLogicRect(rDevice.PixelToLogic(aBackground));
-            //tdf#100925, rhbz#1283420, Draw some text here, to get
-            //X11CairoTextRender::getCairoContext called, so that the forced 
read
-            //from the underlying X Drawable gets it to sync.
-            rDevice.DrawText(aLogicRect.BottomLeft(), " ");
-            rDevice.DrawRect(aLogicRect);
-
-            tools::Rectangle aEditRect(Point(nScrX, nScrY), 
Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
-            pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
-        }
+        tools::Rectangle aEditRect(Point(nScrX, nScrY), 
Size(aOutputData.GetScrW(), aOutputData.GetScrH()));
+        pEditView->Paint(rDevice.PixelToLogic(aEditRect), &rDevice);
 
         rDevice.SetMapMode(MapMode(MapUnit::MapPixel));
 
diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx
index 4ce7acd94391..964ceba34688 100644
--- a/sc/source/ui/view/viewdata.cxx
+++ b/sc/source/ui/view/viewdata.cxx
@@ -2248,6 +2248,7 @@ void ScViewData::EditGrowY( bool bInitial )
 
 void ScViewData::ResetEditView()
 {
+    LOKEditViewHistory::Update(/*bRemove: */ true);
     EditEngine* pEngine = nullptr;
     for (sal_uInt16 i=0; i<4; i++)
     {
@@ -2270,6 +2271,7 @@ void ScViewData::ResetEditView()
 
 void ScViewData::KillEditView()
 {
+    LOKEditViewHistory::Update(/*bRemove: */ true);
     for (sal_uInt16 i=0; i<4; i++)
         if (pEditView[i])
         {
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 2aa5792ebe1e..4a59ffbd3322 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -1133,4 +1133,82 @@ SfxLokLanguageGuard::~SfxLokLanguageGuard()
     comphelper::LibreOfficeKit::setLocale(m_pOldShell->GetLOKLocale());
 }
 
+LOKEditViewHistory::EditViewHistoryMap LOKEditViewHistory::maEditViewHistory;
+
+
+void LOKEditViewHistory::Update(bool bRemove)
+{
+    if (!comphelper::LibreOfficeKit::isActive())
+        return;
+
+    static std::mutex aMutex;
+    SfxViewShell* pViewShell = SfxViewShell::Current();
+    if (pViewShell)
+    {
+        std::lock_guard<std::mutex> aLockGuard{aMutex};
+        int nDocId = pViewShell->GetDocId().get();
+        if (maEditViewHistory.find(nDocId) != maEditViewHistory.end())
+            maEditViewHistory[nDocId].remove(pViewShell);
+        if (!bRemove)
+        {
+            maEditViewHistory[nDocId].push_back(pViewShell);
+            if (maEditViewHistory[nDocId].size() > 10)
+                maEditViewHistory[nDocId].pop_front();
+        }
+    }
+}
+
+ViewShellList LOKEditViewHistory::GetHistoryForDoc(ViewShellDocId aDocId)
+{
+    int nDocId = aDocId.get();
+    ViewShellList aResult;
+    if (maEditViewHistory.find(nDocId) != maEditViewHistory.end())
+        aResult = maEditViewHistory.at(nDocId);
+    return aResult;
+}
+
+ ViewShellList LOKEditViewHistory::GetSortedViewsForDoc(ViewShellDocId aDocId)
+ {
+     ViewShellList aEditViewHistoryForDoc = 
LOKEditViewHistory::GetHistoryForDoc(aDocId);
+     // all views where document is loaded
+     ViewShellList aCurrentDocViewList;
+     // active views that are listed in the edit history
+     ViewShellList aEditedViewList;
+
+     // Populate aCurrentDocViewList and aEditedViewList
+     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
+     while (pViewShell)
+     {
+         if (pViewShell->GetDocId() == aDocId)
+         {
+             if (aEditViewHistoryForDoc.empty() ||
+                 std::find(aEditViewHistoryForDoc.begin(), 
aEditViewHistoryForDoc.end(),
+                           pViewShell) == aEditViewHistoryForDoc.end())
+             {
+                 // append views not listed in the edit history;
+                 // the edit history is limited to 10 views,
+                 // so it could miss some view where in place editing is 
occurring
+                 aCurrentDocViewList.push_back(pViewShell);
+             }
+             else
+             {
+                 // view is listed in the edit history
+                 aEditedViewList.push_back(pViewShell);
+             }
+         }
+         pViewShell = SfxViewShell::GetNext(*pViewShell);
+     }
+
+     // in case some no more active view needs to be removed from the history
+     aEditViewHistoryForDoc.remove_if(
+         [&aEditedViewList](SfxViewShell* pHistoryItem) {
+             return std::find(aEditedViewList.begin(), aEditedViewList.end(), 
pHistoryItem) == aEditedViewList.end();
+         });
+
+     // place views belonging to the edit history at the end
+     aCurrentDocViewList.splice(aCurrentDocViewList.end(), 
aEditViewHistoryForDoc);
+
+     return aCurrentDocViewList;
+ }
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Reply via email to