[Libreoffice-commits] core.git: Branch 'feature/BorderlineFix' - 282 commits - avmedia/source basctl/source basegfx/source basic/source bin/gen-boost-headers bin/list-uitest.py bin/oss-fuzz-build.sh bridges/source canvas/source chart2/source codemaker/source comphelper/source compilerplugins/clang config_host/config_gtk3_kde5.h.in config_host/config_kde5.h.in config_host/config_vclplug.h.in config_host.mk.in configure.ac connectivity/source cppcanvas/source cui/source dbaccess/inc dbaccess/Library_dbahsql.mk dbaccess/Library_dba.mk dbaccess/Module_dbaccess.mk dbaccess/qa dbaccess/README.vars dbaccess/source desktop/source download.lst drawinglayer/source editeng/source embedserv/source extensions/qa extensions/source external/boost external/clew external/curl filter/qa filter/source forms/source fpicker/source framework/inc framework/qa framework/source helpcontent2 hwpfilter/source i18nlangtag/source i18npool/source i18nutil/source include/animations include/basegfx include/basic include/comphel per include/connectivity include/cppcanvas include/drawinglayer include/editeng include/filter include/i18nutil include/LibreOfficeKit include/oox include/osl include/sal include/sfx2 include/svl include/svtools include/svx include/test include/toolkit include/vcl include/xmloff ios/CustomTarget_iOS_link.mk ios/CustomTarget_iOS_prelink.mk ios/CustomTarget_iOS_setup.mk ios/LibreOfficeLight ios/Module_ios.mk ios/StaticLibrary_iOSkit.mk io/test jurt/com jurt/source lingucomponent/source lotuswordpro/source nlpsolver/ThirdParty odk/examples offapi/com officecfg/registry oox/source package/source postprocess/Rdb_services.mk qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/tests readlicense_oo/license reportbuilder/java RepositoryExternal.mk Repository.mk ridljar/com sal/osl sal/qa sal/rtl sax/source sax/test sc/inc scp2/InstallScript_setup_osl.mk scp2/Module_scp2.mk sc/qa scripting/examples scripting/java scripting/source sc/sdi sc/source sc/uiconfig sdext/source sd/inc sd/qa sd/source sfx2/source shell/Library_kde5be.mk shell/Module_shell.mk shell/source slideshow/source solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild solenv/vs soltools/cpp starmath/inc starmath/source stoc/test svgio/source svl/source svtools/qa svtools/source svx/inc svx/Library_svxcore.mk svx/Library_svx.mk svx/source sw/inc sw/qa sw/source sw/uiconfig test/Library_subsequenttest.mk test/source toolkit/source toolkit/test tools/source translations ucb/source udkapi/com UnoControls/source unotools/source vcl/CustomTarget_gtk3_kde5_moc.mk vcl/Executable_lo_kde5filepicker.mk vcl/headless vcl/inc vcl/Library_vclplug_gtk3_kde5.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/quartz vcl/source vcl/unx vcl/workben winaccessibility/source writerfilter/source writerperfect/source xmloff/inc xmloff/source xmlreader/source xmlsecurity/inc xmlsecurity/source

Armin Le Grand Armin.Le.Grand at cib.de
Sat Jan 27 16:25:54 UTC 2018


Rebased ref, commits from common ancestor:
commit 717c9ff047488c950d062a0ca27bd83e803a31ca
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Jan 24 15:25:40 2018 +0100

    BorderlineFix: Use svx::frame::Array tooling in Draw/Impress
    
    For creating the needed BorderPrimitives for TableCells for the
    Tables used in Draw/Impress, adapt the ViewContactOfTableObj doing
    this to use svx::frame::Array tooling now. This will correct the
    error for not taking the neighboured connects for merged cells
    into account and unify one more space to the same tooling.
    
    Change-Id: I2e6f732985e9b963359f156628bd29ddfec1a80c

diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk
index 6bdbadaf2e3b..ad1b1dc3a423 100644
--- a/svx/Library_svx.mk
+++ b/svx/Library_svx.mk
@@ -128,7 +128,6 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
     svx/source/dialog/fntctrl \
     svx/source/dialog/fontlb \
     svx/source/dialog/fontwork \
-    svx/source/dialog/framelinkarray \
     svx/source/dialog/frmdirlbox \
     svx/source/dialog/frmsel \
     svx/source/dialog/graphctl \
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 5bfbf899034d..603860d7f11b 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -116,6 +116,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
     svx/source/dialog/dlgutil \
     svx/source/dialog/hexcolorcontrol \
     svx/source/dialog/framelink \
+    svx/source/dialog/framelinkarray \
     svx/source/dialog/langbox \
     svx/source/dialog/pagenumberlistbox \
     svx/source/dialog/papersizelistbox \
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index bc8a50a3d3cf..7cd4b26027dc 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -21,6 +21,7 @@
 
 #include <math.h>
 #include <vector>
+#include <set>
 #include <algorithm>
 #include <vcl/outdev.hxx>
 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 448a0b407f2a..4a5741cd0545 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -36,8 +36,10 @@
 #include <drawinglayer/attribute/sdrlineattribute.hxx>
 #include <drawinglayer/attribute/sdrshadowattribute.hxx>
 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <svx/framelink.hxx>
+#include <svx/framelinkarray.hxx>
 
 #include <cell.hxx>
 #include "tablelayouter.hxx"
@@ -196,42 +198,6 @@ namespace sdr
             return svx::frame::Style();
         }
 
-        void createForVector(bool bHor, drawinglayer::primitive2d::Primitive2DContainer& rContainer, const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX,
-            const svx::frame::Style& rLine,
-            const svx::frame::Style& rLeftA, const svx::frame::Style& rLeftB, const svx::frame::Style& rLeftC,
-            const svx::frame::Style& rRightA, const svx::frame::Style& rRightB, const svx::frame::Style& rRightC)
-        {
-            /// top-left and bottom-right Style Tables
-            const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX));
-
-            /// Fill top-left Style Table
-            svx::frame::StyleVectorTable aStart;
-
-            aStart.add(rLeftA, rX, -aY, bHor); // bHor ? true : false));
-            aStart.add(rLeftB, rX, -rX, true); // bHor ? true : true));
-            aStart.add(rLeftC, rX, aY, !bHor); // bHor ? false : true));
-            aStart.sort();
-
-            /// Fill bottom-right Style Table
-            svx::frame::StyleVectorTable aEnd;
-            const basegfx::B2DVector aAxis(-rX);
-
-            aEnd.add(rRightA, aAxis, -aY, bHor); // bHor ? true : false));
-            aEnd.add(rRightB, aAxis, rX, false); // bHor ? false : false));
-            aEnd.add(rRightC, aAxis, aY, !bHor); // bHor ? false : true));
-            aEnd.sort();
-
-            CreateBorderPrimitives(
-                rContainer,
-                rOrigin,
-                rX,
-                rLine,
-                aStart,
-                aEnd,
-                nullptr
-            );
-        }
-
         drawinglayer::primitive2d::Primitive2DContainer ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const
         {
             const sdr::table::SdrTableObj& rTableObj = static_cast<const sdr::table::SdrTableObj&>(GetSdrObject());
@@ -249,7 +215,7 @@ namespace sdr
 
                 if(nAllCount)
                 {
-                    const sdr::table::TableLayouter& rTableLayouter = rTableObj.getTableLayouter();
+                    const sdr::table::TableLayouter& rTableLayouter(rTableObj.getTableLayouter());
                     const bool bIsRTL(css::text::WritingMode_RL_TB == rTableObj.GetWritingMode());
                     sdr::table::CellPos aCellPos;
                     sdr::table::CellRef xCurrentCell;
@@ -258,19 +224,59 @@ namespace sdr
                     // create range using the model data directly. This is in SdrTextObj::aRect which i will access using
                     // GetGeoRect() to not trigger any calculations. It's the unrotated geometry.
                     const tools::Rectangle& rObjectRectangle(rTableObj.GetGeoRect());
-                    const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom());
+                    const basegfx::B2DRange aObjectRange(
+                        rObjectRectangle.Left(), rObjectRectangle.Top(),
+                        rObjectRectangle.Right(), rObjectRectangle.Bottom());
+
+                    // To create the CellBorderPrimitives, use the tolling from svx::frame::Array
+                    // which is capable of creating the needed visualization. Fill it during the
+                    // anyways needed run over the table.
+                    svx::frame::Array aArray;
 
-                    // for each cell we need potentially a cell primitive and a border primitive
-                    // (e.g. single cell). Prepare sequences and input counters
-                    drawinglayer::primitive2d::Primitive2DContainer aBorderSequence;
+                    // initialize CellBorderArray for primitive creation
+                    aArray.Initialize(nRowCount, nColCount);
 
                     // create single primitives per cell
                     for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
                     {
+                        // add RowHeight to CellBorderArray for primitive creation
+                        aArray.SetRowHeight(aCellPos.mnRow, rTableLayouter.getRowHeight(aCellPos.mnRow));
+
                         for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++)
                         {
+                            // add ColWidth to CellBorderArray for primitive creation, only
+                            // needs to be done in the 1st run
+                            if(0 == aCellPos.mnRow)
+                            {
+                                aArray.SetColWidth(aCellPos.mnCol, rTableLayouter.getColumnWidth(aCellPos.mnCol));
+                            }
+
+                            // access the cell
                             xCurrentCell.set(dynamic_cast< sdr::table::Cell* >(xTable->getCellByPosition(aCellPos.mnCol, aCellPos.mnRow).get()));
 
+                            if(xCurrentCell.is())
+                            {
+                                // copy styles for current cell to CellBorderArray for primitive creation
+                                aArray.SetCellStyleLeft(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleRight(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol + 1, aCellPos.mnRow, false, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleTop(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, true, nColCount, nRowCount, bIsRTL));
+                                aArray.SetCellStyleBottom(aCellPos.mnCol, aCellPos.mnRow, impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow + 1, true, nColCount, nRowCount, bIsRTL));
+
+                                // ignore merged cells (all except the top-left of a merged cell)
+                                if(!xCurrentCell->isMerged())
+                                {
+                                    // check if we are the top-left of a merged cell
+                                    const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
+                                    const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
+
+                                    if(nXSpan > 1 || nYSpan > 1)
+                                    {
+                                        // if merged, set so at CellBorderArray for primitive creation
+                                        aArray.SetMergedRange(aCellPos.mnCol, aCellPos.mnRow, aCellPos.mnCol + nXSpan - 1, aCellPos.mnRow + nYSpan - 1);
+                                    }
+                                }
+                            }
+
                             if(xCurrentCell.is() && !xCurrentCell->isMerged())
                             {
                                 if(rTableLayouter.getCellArea(xCurrentCell, aCellPos, aCellArea))
@@ -318,77 +324,54 @@ namespace sdr
                                                 aCellMatrix, aAttribute));
                                         aRetval.append(xCellReference);
                                     }
-
-                                    // handle cell borders
-                                    const sal_Int32 nX(bIsRTL ? nColCount - aCellPos.mnCol : aCellPos.mnCol);
-                                    const sal_Int32 nY(aCellPos.mnRow);
-
-                                    // get access values for X,Y at the cell's end
-                                    const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
-                                    const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
-                                    const sal_Int32 nXRight(bIsRTL ? nX - nXSpan : nX + nXSpan);
-                                    const sal_Int32 nYBottom(nY + nYSpan);
-
-                                    // get basic lines
-                                    const svx::frame::Style aLeftLine(impGetLineStyle(rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL));
-                                    //To resolve the bug fdo#59117
-                                    //In RTL table as BottomLine & TopLine are drawn from Left Side to Right, nX should be nX-1
-                                    const svx::frame::Style aBottomLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nYBottom, true, nColCount, nRowCount, bIsRTL));
-                                    const svx::frame::Style aRightLine(impGetLineStyle(rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL));
-                                    const svx::frame::Style aTopLine(impGetLineStyle(rTableLayouter, bIsRTL?nX-1:nX, nY, true, nColCount, nRowCount, bIsRTL));
-
-                                    if(aLeftLine.IsUsed() || aBottomLine.IsUsed() || aRightLine.IsUsed() || aTopLine.IsUsed())
-                                    {
-                                        // get the neighbor cells' borders
-                                        const svx::frame::Style aLeftFromTLine(impGetLineStyle(rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aRightFromTLine(impGetLineStyle(rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aTopFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight, nY, true, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aBottomFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, true, nColCount, nRowCount, bIsRTL));
-
-                                        // get cell coordinate system
-                                        const basegfx::B2DPoint aOrigin(aCellMatrix * basegfx::B2DPoint(0.0, 0.0));
-                                        const basegfx::B2DVector aX(aCellMatrix * basegfx::B2DVector(1.0, 0.0));
-                                        const basegfx::B2DVector aY(aCellMatrix * basegfx::B2DVector(0.0, 1.0));
-
-                                        if(aLeftLine.IsUsed())
-                                        {
-                                            createForVector(false, aBorderSequence, aOrigin, aY, aLeftLine,
-                                                aTopLine, aLeftFromTLine, aTopFromLLine,
-                                                aBottomLine, aLeftFromBLine, aBottomFromLLine);
-                                        }
-
-                                        if(aBottomLine.IsUsed())
-                                        {
-                                            createForVector(true, aBorderSequence, aOrigin + aY, aX, aBottomLine,
-                                                aLeftLine, aBottomFromLLine, aLeftFromBLine,
-                                                aRightLine, aBottomFromRLine, aRightFromBLine);
-                                        }
-
-                                        if(aRightLine.IsUsed())
-                                        {
-                                            createForVector(false, aBorderSequence, aOrigin + aX, aY, aRightLine,
-                                                aTopFromRLine, aRightFromTLine, aTopLine,
-                                                aBottomFromRLine, aRightFromBLine, aBottomLine);
-                                        }
-
-                                        if(aTopLine.IsUsed())
-                                        {
-                                            createForVector(true, aBorderSequence, aOrigin, aX, aTopLine,
-                                                aLeftFromTLine, aTopFromLLine, aLeftLine,
-                                                aRightFromTLine, aTopFromRLine, aRightLine);
-                                        }
-                                    }
                                 }
                             }
                         }
                     }
 
-                    // append Border info to target. We want fillings and text first
-                    aRetval.append(aBorderSequence);
+                    // now create all CellBorderPrimitives
+                    const drawinglayer::primitive2d::Primitive2DContainer aCellBorderPrimitives(aArray.CreateB2DPrimitiveArray());
+
+                    if(!aCellBorderPrimitives.empty())
+                    {
+                        // this is already scaled (due to Table in non-uniform coordinates), so
+                        // first transform removing scale
+                        basegfx::B2DHomMatrix aTransform(
+                            basegfx::utils::createScaleB2DHomMatrix(
+                                1.0 / aObjectRange.getWidth(),
+                                1.0 / aObjectRange.getHeight()));
+
+                        // If RTL, mirror the whole unified table in X and move right.
+                        // This is much easier than taking this into account for the whole
+                        // index calcualtions
+                        if(bIsRTL)
+                        {
+                            aTransform.scale(-1.0, 1.0);
+                            aTransform.translate(1.0, 0.0);
+                        }
+
+                        // create object matrix
+                        const GeoStat& rGeoStat(rTableObj.GetGeoStat());
+                        const double fShearX(rGeoStat.nShearAngle ? tan((36000 - rGeoStat.nShearAngle) * F_PI18000) : 0.0);
+                        const double fRotate(rGeoStat.nRotationAngle ? (36000 - rGeoStat.nRotationAngle) * F_PI18000 : 0.0);
+                        const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
+                            aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
+                            aObjectRange.getMinX(), aObjectRange.getMinY()));
+
+                        // add object matrix to transform. By doing so theoretically
+                        // CellBorders could be also rotated/sheared for the first time ever.
+                        // To completely make that work, the primitives already created in
+                        // aRetval would also have to be based on ObjectMatrix, not only on
+                        // ObjectRange as it currently is.
+                        aTransform *= aObjectMatrix;
+
+                        // create a transform primitive with this and embed CellBorders
+                        // and append to retval
+                        aRetval.append(
+                            new drawinglayer::primitive2d::TransformPrimitive2D(
+                                aTransform,
+                                aCellBorderPrimitives));
+                    }
                 }
 
                 if(!aRetval.empty())
commit a23a33bb005d0aa2fad56a78e89a7724be231a21
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Jan 24 12:05:19 2018 +0100

    BorderlineFix: Corrected Draw/Impress TableStyle accesses
    
    In Draw/Impress the indices for accessing the correct
    neighbouring TableStyles were wrong and thus created wrong
    visualizations, corrected that.
    
    Change-Id: Iebc5f294adb62fa4c6358e2f8c27d29cc3163fbc

diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx
index 7ca200fc0e6e..448a0b407f2a 100644
--- a/svx/source/table/viewcontactoftableobj.cxx
+++ b/svx/source/table/viewcontactoftableobj.cxx
@@ -341,13 +341,13 @@ namespace sdr
                                     {
                                         // get the neighbor cells' borders
                                         const svx::frame::Style aLeftFromTLine(impGetLineStyle(rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
+                                        const svx::frame::Style aLeftFromBLine(impGetLineStyle(rTableLayouter, nX, nYBottom, false, nColCount, nRowCount, bIsRTL));
                                         const svx::frame::Style aRightFromTLine(impGetLineStyle(rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom + 1, false, nColCount, nRowCount, bIsRTL));
+                                        const svx::frame::Style aRightFromBLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, false, nColCount, nRowCount, bIsRTL));
                                         const svx::frame::Style aTopFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nY, true, nColCount, nRowCount, bIsRTL));
+                                        const svx::frame::Style aTopFromRLine(impGetLineStyle(rTableLayouter, nXRight, nY, true, nColCount, nRowCount, bIsRTL));
                                         const svx::frame::Style aBottomFromLLine(impGetLineStyle(rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
-                                        const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight + 1, nYBottom, true, nColCount, nRowCount, bIsRTL));
+                                        const svx::frame::Style aBottomFromRLine(impGetLineStyle(rTableLayouter, nXRight, nYBottom, true, nColCount, nRowCount, bIsRTL));
 
                                         // get cell coordinate system
                                         const basegfx::B2DPoint aOrigin(aCellMatrix * basegfx::B2DPoint(0.0, 0.0));
commit 4f7e56916a5e9ba556596ed84dd778975efdad1b
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 17:38:34 2018 +0100

    BorderlineFix: Fix WriterPaint if scrolling CellTableBorders
    
    Similar to CalcBorders in Writer the overlap regions for
    FrameBorders have to be taken into account when repainting the
    CellBordes of WriterTables
    
    Change-Id: I488ba158e1de579bfb06b9c8353adaa2cac706c6

diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 70781515d300..dc2837e2eed9 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2439,11 +2439,33 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
             {
                 aRepaintRect.Height( 2 * nRepaintRectSize );
                 aRepaintRect.Pos().Y() -= nRepaintRectSize;
+
+                // To decide on visibility it is also necessary to expand the RepaintRect
+                // to left/right according existing BorderLine overlap matchings, else there
+                // will be repaint errors when scrolling in e.t TripleLine BorderLines.
+                // aStyles[1] == aLFromT, aStyles[3] == aLFromB, aStyles[4] == aRFromT, aStyles[6] == aRFromB
+                if(aStyles[1].IsUsed() || aStyles[3].IsUsed() || aStyles[4].IsUsed() || aStyles[6].IsUsed())
+                {
+                    const double fLineWidthMaxLeft(std::max(aStyles[1].GetWidth(), aStyles[3].GetWidth()));
+                    const double fLineWidthMaxRight(std::max(aStyles[4].GetWidth(), aStyles[6].GetWidth()));
+                    aRepaintRect.Width(aRepaintRect.Width() + (fLineWidthMaxLeft + fLineWidthMaxRight));
+                    aRepaintRect.Pos().X() -= fLineWidthMaxLeft;
+                }
             }
             else
             {
                 aRepaintRect.Width( 2 * nRepaintRectSize );
                 aRepaintRect.Pos().X() -= nRepaintRectSize;
+
+                // Accordingly to horizontal case, but for top/bottom
+                // aStyles[3] == aTFromR, aStyles[1] == aTFromL, aStyles[6] == aBFromR, aStyles[4] == aBFromL
+                if(aStyles[3].IsUsed() || aStyles[1].IsUsed() || aStyles[6].IsUsed() || aStyles[4].IsUsed())
+                {
+                    const double fLineWidthMaxTop(std::max(aStyles[3].GetWidth(), aStyles[1].GetWidth()));
+                    const double fLineWidthMaxBottom(std::max(aStyles[6].GetWidth(), aStyles[4].GetWidth()));
+                    aRepaintRect.Height(aRepaintRect.Height() + (fLineWidthMaxTop + fLineWidthMaxBottom));
+                    aRepaintRect.Pos().Y() -= fLineWidthMaxTop;
+                }
             }
 
             if (!rRect.IsOver(aRepaintRect))
commit 214d33866b1c3c3fa8fa0128534517bf83cb2d12
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 16:06:19 2018 +0100

    BorderlineFix: Fixed visual updates when scrolling
    
    For Cells with DoubleLine the connections to perpendicular
    DoubleLine-Styles may have to be displayed in a Cell which
    is 'around' the orig cell in a Cell-Border of one. To represent
    that and to avoid repaint errors when scrolling in, the preparation
    of Primitives has to take accordingly more neighbour cells into
    account. Tested this change with the usages in Calc, UI (Dialogs)
    and Calc exports Print/PrintPreview/PDF. This does not affect
    Tables in Writer and/or Draw/Impress.
    
    Change-Id: I3bcc68cdf7b4fc1825a87a9773892c359421024e

diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ab6db75799e3..bc8a50a3d3cf 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1061,18 +1061,39 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     DBG_FRAME_CHECK_COLROW( nFirstCol, nFirstRow, "CreateB2DPrimitiveRange" );
     DBG_FRAME_CHECK_COLROW( nLastCol, nLastRow, "CreateB2DPrimitiveRange" );
 
+    // It may be necessary to extend the loop ranges by one cell to the outside,
+    // when possible. This is needed e.g. when there is in Calc a Cell with an
+    // upper CellBorder using DoubleLine and that is right/left connected upwards
+    // to also DoubleLine. These upper DoubleLines will be extended to meet the
+    // lower of the upper CellBorder and thus have graphical parts that are
+    // displayed one cell below and right/left of the target cell - analog to
+    // other examples in all other directions.
+    // It would be possible to explicitely test this (if possible by indices at all)
+    // looping and testing the styles in the outer cells to detect this, but since
+    // for other usages (e.g. UI) usually nFirstRow==0 and nLastRow==GetRowCount()-1
+    // (and analog for Col) it is okay to just expand the range when available.
+    // Do *not* change nFirstRow/nLastRow due to these needed to the boolean tests
+    // below (!)
+    // Checked usages, this method is used in Calc EditView/Print/Export stuff and
+    // in UI (Dialog), not for Writer Tables and Draw/Impress tables. All usages
+    // seem okay with this change, so I will add it.
+    const size_t nStartRow(nFirstRow > 0 ? nFirstRow - 1 : nFirstRow);
+    const size_t nEndRow(nLastRow < GetRowCount() - 1 ? nLastRow + 1 : nLastRow);
+    const size_t nStartCol(nFirstCol > 0 ? nFirstCol - 1 : nFirstCol);
+    const size_t nEndCol(nLastCol < GetColCount() - 1 ? nLastCol + 1 : nLastCol);
+
     // various primitive sequences to collect the different border types
     drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
-    std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1);
+    std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nEndCol - nStartCol + 1);
     drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
 
     // remember for which merged cells crossed lines were already created. To
     // do so, hold the size_t cell index in a set for fast check
     std::set< size_t > aMergedCells;
 
-    for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
+    for (size_t nRow(nStartRow); nRow <= nEndRow; ++nRow)
     {
-        for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
+        for (size_t nCol(nStartCol); nCol <= nEndCol; ++nCol)
         {
             // get Cell and CoordinateSystem (*only* for this Cell, do *not* expand for
             // merged cells (!)), check if used (non-empty vectors)
@@ -1139,7 +1160,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rLeft.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], true, pForceColor);
+                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], true, pForceColor);
                     }
                 }
 
@@ -1151,7 +1172,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rRight.IsUsed())
                     {
-                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], false, pForceColor);
+                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], false, pForceColor);
                     }
                 }
 
commit 7927927ccd594418e9497c66f18a75b1cbbcbccf
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Tue Jan 23 10:29:44 2018 +0100

    BorderlineFix: Corrected handling for 'rotated' CellBorders
    
    CellBorders can be rotated (including their Text) and need special
    visualization that is based on an own sheared/rotated coordinate
    system. Currently only possible for single cells (not merged ones)
    and needs to handle all borders (also bottom-right directly in the
    rotated cell, not in the neighboured ones to have the geometry,
    plus avoiding these in the non-rotated neighbour cells.
    Also corrected adding CellRotation data to svx::frame::Array
    in calc using SetCellRotations() which now gets called in the
    ScOutputData constructor to ensure it gets called in all places
    where it is used.
    
    Change-Id: I47bdfc29ba5ca76bbc07d98cb64733f867b1ee20

diff --git a/sc/source/ui/inc/output.hxx b/sc/source/ui/inc/output.hxx
index f23dabae3de0..c41433609b9e 100644
--- a/sc/source/ui/inc/output.hxx
+++ b/sc/source/ui/inc/output.hxx
@@ -255,6 +255,11 @@ private:
     long SetEngineTextAndGetWidth( DrawEditParam& rParam, const OUString& rSetString,
                                    long& rNeededPixel, long nAddWidthPixels );
 
+    // Check for and set cell rotations at OutputData to have it available
+    // in the svx tooling to render the borders. Moved to private section
+    // and the single call to end of constructor to be sure this always happens
+    void    SetCellRotations();
+
 public:
     /**
      * @param nNewScrX: X-Offset in the output device for the table
@@ -311,8 +316,6 @@ public:
 
                     // with logic MapMode set!
     void    DrawEdit(bool bPixelToLogic);
-
-    void    SetCellRotations();
     void    DrawRotated(bool bPixelToLogic);        // logical
 
     void    DrawClear();
diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx
index 22e07763decb..64cd440e9902 100644
--- a/sc/source/ui/view/gridwin4.cxx
+++ b/sc/source/ui/view/gridwin4.cxx
@@ -696,10 +696,6 @@ void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableI
         pContentDev->SetMapMode(aCurrentMapMode);
     }
 
-    // check for and set cell rotations at OutputData to have it available
-    // in the svx tooling to render the borders
-    aOutputData.SetCellRotations();
-
     if ( rDoc.HasBackgroundDraw( nTab, aDrawingRectLogic ) )
     {
         pContentDev->SetMapMode(MapMode(MapUnit::MapPixel));
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index bd3687cd1cd3..064bb14ce1a1 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -214,6 +214,9 @@ ScOutputData::ScOutputData( OutputDevice* pNewDev, ScOutputType eNewType,
 
     bTabProtected = mpDoc->IsTabProtected( nTab );
     bLayoutRTL = mpDoc->IsLayoutRTL( nTab );
+
+    // always needed, so call at the end of the constructor
+    SetCellRotations();
 }
 
 ScOutputData::~ScOutputData()
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index 096216210585..ab6db75799e3 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1092,9 +1092,21 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 const bool bFirstRow(nRow == nFirstRow);
                 const bool bLastRow(nRow == nLastRow);
 
+                // handle rotation: If cell is rotated, handle lower/right edge inside
+                // this local geometry due to the created CoordinateSystem already representing
+                // the needed transformations.
+                const bool bRotated(rCell.IsRotated());
+
+                // Additionally avoid double-handling by supressing handling when self not roated,
+                // but above/left is rotated and thus already handled. Two directly connected
+                // rotated will paint/create both edges, they might be rotated differently.
+                const bool bSuppressAbove(!bRotated && nRow > nFirstRow && CELL(nCol, nRow - 1).IsRotated());
+                const bool bSupressLeft(!bRotated && nCol > nFirstCol && CELL(nCol - 1, nRow).IsRotated());
+
                 // create upper line for this Cell
-                if (!bOverlapY      // true for first line in merged cells or cells
-                    || bFirstRow)   // true for non_Calc usages of this tooling
+                if ((!bOverlapY         // true for first line in merged cells or cells
+                    || bFirstRow)       // true for non_Calc usages of this tooling
+                    && !bSuppressAbove) // true when above is not rotated, so edge is already handled (see bRotated)
                 {
                     // get CellStyle - method will take care to get the correct one, e.g.
                     // for merged cells (it uses ORIGCELL that works with topLeft's of these)
@@ -1107,7 +1119,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create lower line for this Cell
-                if (bLastRow)       // true for non_Calc usages of this tooling
+                if (bLastRow       // true for non_Calc usages of this tooling
+                    || bRotated)   // true if cell is rotated, handle lower edge in local geometry
                 {
                     const Style& rBottom(GetCellStyleBottom(nCol, nRow));
 
@@ -1118,8 +1131,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create left line for this Cell
-                if (!bOverlapX      // true for first column in merged cells or cells
-                    || bFirstCol)   // true for non_Calc usages of this tooling
+                if ((!bOverlapX         // true for first column in merged cells or cells
+                    || bFirstCol)       // true for non_Calc usages of this tooling
+                    && !bSupressLeft)   // true when left is not rotated, so edge is already handled (see bRotated)
                 {
                     const Style& rLeft(GetCellStyleLeft(nCol, nRow));
 
@@ -1130,7 +1144,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 }
 
                 // create right line for this Cell
-                if (bLastCol)       // true for non_Calc usages of this tooling
+                if (bLastCol        // true for non_Calc usages of this tooling
+                    || bRotated)    // true if cell is rotated, handle right edge in local geometry
                 {
                     const Style& rRight(GetCellStyleRight(nCol, nRow));
 
commit 9d4fe6487d513e70b3a34c7c00dfb1775ef7c900
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Mon Jan 22 14:33:20 2018 +0100

    BorderlineFix: Avoid BorderLines to be too prolonged
    
    For MergedCells there was an effect that the BorderLines
    were painted too far in PrintPreview/Print/PDF visualization,
    found reason and changed. Checked (hopefully) all usages,
    looks good.
    
    Change-Id: I0acf8dcb20548a98533f3ab317ac72c0d0f0a947

diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index e135e371319c..b73531b06e47 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -290,7 +290,7 @@ public:
     long                GetHeight() const;
 
     /** Returns the output range of the cell (nCol,nRow).
-        Returns total output range of merged ranges. */
+        Returns total output range of merged ranges, if bExpandMerged is true. */
     basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const;
 
     // mirroring --------------------------------------------------------------
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ac47053155ec..096216210585 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -840,24 +840,44 @@ long Array::GetHeight() const
 
 basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const
 {
-    size_t nFirstCol = bExpandMerged ? mxImpl->GetMergedFirstCol( nCol, nRow ) : nCol;
-    size_t nFirstRow = bExpandMerged ? mxImpl->GetMergedFirstRow( nCol, nRow ) : nRow;
-    size_t nLastCol = bExpandMerged ? mxImpl->GetMergedLastCol( nCol, nRow ) : nCol;
-    size_t nLastRow = bExpandMerged ? mxImpl->GetMergedLastRow( nCol, nRow ) : nRow;
-    const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
-    const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
-    tools::Rectangle aRect(aPoint, aSize);
-
-    // adjust rectangle for partly visible merged cells
-    const Cell& rCell = CELL( nCol, nRow );
-    if( rCell.IsMerged() )
+    if(bExpandMerged)
     {
-        aRect.Left() -= rCell.mnAddLeft;
-        aRect.Right() += rCell.mnAddRight;
-        aRect.Top() -= rCell.mnAddTop;
-        aRect.Bottom() += rCell.mnAddBottom;
+        // get the Range of the fully expanded cell (if merged)
+        const size_t nFirstCol(mxImpl->GetMergedFirstCol( nCol, nRow ));
+        const size_t nFirstRow(mxImpl->GetMergedFirstRow( nCol, nRow ));
+        const size_t nLastCol(mxImpl->GetMergedLastCol( nCol, nRow ));
+        const size_t nLastRow(mxImpl->GetMergedLastRow( nCol, nRow ));
+        const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
+        const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
+        tools::Rectangle aRect(aPoint, aSize);
+
+        // adjust rectangle for partly visible merged cells
+        const Cell& rCell = CELL( nCol, nRow );
+
+        if( rCell.IsMerged() )
+        {
+            // not *sure* what exactly this is good for,
+            // it is just a hard set extension at merged cells,
+            // probably *should* be included in the above extended
+            // GetColPosition/GetColWidth already. This might be
+            // added due to GetColPosition/GetColWidth not working
+            // correcly over PageChanges (if used), but not sure.
+            aRect.Left() -= rCell.mnAddLeft;
+            aRect.Right() += rCell.mnAddRight;
+            aRect.Top() -= rCell.mnAddTop;
+            aRect.Bottom() += rCell.mnAddBottom;
+        }
+
+        return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
+    }
+    else
+    {
+        const Point aPoint( GetColPosition( nCol ), GetRowPosition( nRow ) );
+        const Size aSize( GetColWidth( nCol, nCol ) + 1, GetRowHeight( nRow, nRow ) + 1 );
+        const tools::Rectangle aRect(aPoint, aSize);
+
+        return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
     }
-    return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
 }
 
 // mirroring
@@ -1054,7 +1074,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     {
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
-            // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
+            // get Cell and CoordinateSystem (*only* for this Cell, do *not* expand for
+            // merged cells (!)), check if used (non-empty vectors)
             const Cell& rCell(CELL(nCol, nRow));
             basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
             basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
@@ -1153,9 +1174,6 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(bContinue)
                     {
-                        const size_t _nLastCol(mxImpl->GetMergedLastCol(nCol, nRow));
-                        const size_t _nLastRow(mxImpl->GetMergedLastRow(nCol, nRow));
-
                         if(rTLBR.IsUsed())
                         {
                             /// top-left and bottom-right Style Tables
commit 5807f62db5ec9fc9e2b1f21c0af124317f72c5d3
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Jan 19 14:43:24 2018 +0100

    BorderlineFix: Corrected missing borders in print
    
    In Print/PDF/PrintPreview border lines were missing, this
    happened for merged cells. It has to do with access to the
    involved Styles and/or 'Clip' set (to avoid creating everything).
    Thus a 'mixed' usage of cell and merged-cell stuff was needed.
    As it turns out support for this is already there, need to use
    it.
    
    Change-Id: Ic16085b97eef5c79a4501279432f43491bca350e

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 2feaab5af8bf..9b532a2d0d29 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -143,10 +143,6 @@ private:
     /// the impl class holding the data
     std::shared_ptr< implStyle >        maImplStyle;
 
-    /// pointer to Cell using this style. Not member of the
-    /// impl class since multiple Cells may use the same style
-    const Cell*                         mpUsingCell;
-
     /// call to set maImplStyle on demand
     void implEnsureImplStyle();
 
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index ecb3eaace1c6..ac47053155ec 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -1055,17 +1055,14 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
             // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
-            const Cell& rCell = CELL(nCol, nRow);
+            const Cell& rCell(CELL(nCol, nRow));
             basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
             basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
             basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
 
             if(!aX.equalZero() && !aY.equalZero())
             {
-                // for getting correct Style(s) for merged Cells, we need the First(Col/Row)
-                // for access (see accessing Styles below)
-                const size_t _nFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
-                const size_t _nFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                // get needed local values
                 basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
                 const bool bOverlapX(rCell.mbOverlapX);
                 const bool bOverlapY(rCell.mbOverlapY);
@@ -1078,7 +1075,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 if (!bOverlapY      // true for first line in merged cells or cells
                     || bFirstRow)   // true for non_Calc usages of this tooling
                 {
-                    const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);
+                    // get CellStyle - method will take care to get the correct one, e.g.
+                    // for merged cells (it uses ORIGCELL that works with topLeft's of these)
+                    const Style& rTop(GetCellStyleTop(nCol, nRow));
 
                     if(rTop.IsUsed())
                     {
@@ -1089,7 +1088,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 // create lower line for this Cell
                 if (bLastRow)       // true for non_Calc usages of this tooling
                 {
-                    const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);
+                    const Style& rBottom(GetCellStyleBottom(nCol, nRow));
 
                     if(rBottom.IsUsed())
                     {
@@ -1101,7 +1100,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 if (!bOverlapX      // true for first column in merged cells or cells
                     || bFirstCol)   // true for non_Calc usages of this tooling
                 {
-                    const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                    const Style& rLeft(GetCellStyleLeft(nCol, nRow));
 
                     if(rLeft.IsUsed())
                     {
@@ -1112,7 +1111,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 // create right line for this Cell
                 if (bLastCol)       // true for non_Calc usages of this tooling
                 {
-                    const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));
+                    const Style& rRight(GetCellStyleRight(nCol, nRow));
 
                     if(rRight.IsUsed())
                     {
@@ -1122,8 +1121,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                 // check for crossed lines, these need special treatment, especially
                 // for merged cells, see below
-                const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
-                const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
+                const Style& rTLBR(GetCellStyleTLBR(nCol, nRow));
+                const Style& rBLTR(GetCellStyleBLTR(nCol, nRow));
 
                 if(rTLBR.IsUsed() || rBLTR.IsUsed())
                 {
@@ -1131,8 +1130,11 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
 
                     if(rCell.IsMerged())
                     {
-                        // first check if this merged cell was already handled
-                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nFirstCol, _nFirstRow));
+                        // first check if this merged cell was already handled. To do so,
+                        // calculate and use the index of the TopLeft cell
+                        const size_t _nMergedFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
+                        const size_t _nMergedFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nMergedFirstCol, _nMergedFirstRow));
                         bContinue = (aMergedCells.end() == aMergedCells.find(nIndexOfMergedCell));
 
                         if(bContinue)
@@ -1140,7 +1142,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             // not found, add now to mark as handled
                             aMergedCells.insert(nIndexOfMergedCell);
 
-                            // when merged, get extended coordinate system and dependent values
+                            // when merged, get extended coordinate system and derived values
+                            // for the full range of this merged cell
                             aCoordinateSystem = rCell.CreateCoordinateSystem(*this, nCol, nRow, true);
                             aX = basegfx::utils::getColumn(aCoordinateSystem, 0);
                             aY = basegfx::utils::getColumn(aCoordinateSystem, 1);
@@ -1157,8 +1160,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                         {
                             /// top-left and bottom-right Style Tables
                             /// Fill top-left Style Table
-                            const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
-                            const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                            const Style& rTLFromRight(GetCellStyleTop(nCol, nRow));
+                            const Style& rTLFromBottom(GetCellStyleLeft(nCol, nRow));
                             StyleVectorTable aStart;
                             const basegfx::B2DVector aAxisA(aX + aY);
 
@@ -1167,8 +1170,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             aStart.sort();
 
                             /// Fill bottom-right Style Table
-                            const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
-                            const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
+                            const Style& rBRFromBottom(GetCellStyleRight(nCol, nRow));
+                            const Style& rBRFromLeft(GetCellStyleBottom(nCol, nRow));
                             StyleVectorTable aEnd;
                             const basegfx::B2DVector aAxisB(-aX -aY);
 
@@ -1191,8 +1194,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                         {
                             /// bottom-left and top-right Style Tables
                             /// Fill bottom-left Style Table
-                            const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
-                            const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
+                            const Style& rBLFromTop(GetCellStyleLeft(nCol, nRow));
+                            const Style& rBLFromBottom(GetCellStyleBottom(nCol, nRow));
                             StyleVectorTable aStart;
                             const basegfx::B2DVector aAxisA(aX - aY);
 
@@ -1201,8 +1204,8 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                             aStart.sort();
 
                             /// Fill top-right Style Table
-                            const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
-                            const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
+                            const Style& rTRFromLeft(GetCellStyleTop(nCol, nRow));
+                            const Style& rTRFromBottom(GetCellStyleRight(nCol, nRow));
                             StyleVectorTable aEnd;
                             const basegfx::B2DVector aAxisB(aY - aX);
 
commit 039776d397c11d5f51ac3ec49e7e38cc822d66db
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Jan 18 17:07:43 2018 +0100

    BorderlineFix: Need to redesign Borderline paint for Calc
    
    To fix some errors, need to change svx::frame::Array conversion
    to Primitives, especially regarding handling of merged cells.
    These make problems in the currtent form where the full extended
    merged cell tries to be converted. This is bad for cropped stuff
    and also wrong for double-line stuff attaching to a merged cell.
    The solution is to handle cells single and merge created primitives
    which is more expensive but will work. This will involve special
    handling for X-Ed (crossed) and 'roated' Cells. Also need to be
    very careful since all this is used in the meantime for all
    visualizations of Tables in multiple apps/situations.
    
    Change-Id: If0652a3ba97a6f27dd5d782ea22b1514303f3710

diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index ce7f09345a80..2feaab5af8bf 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -150,11 +150,6 @@ private:
     /// call to set maImplStyle on demand
     void implEnsureImplStyle();
 
-    /// need information which cell this style info comes from due to needed
-    /// rotation info (which is in the cell). Rotation depends on the cell.
-    friend class Cell;
-    void SetUsingCell(const Cell* pCell) { mpUsingCell = pCell; }
-
 public:
     /** Constructs an invisible frame style. */
     explicit Style();
@@ -203,9 +198,6 @@ public:
     /** Mirrors this style (exchanges primary and secondary), if it is a double frame style. */
     Style& MirrorSelf();
 
-    /** return the Cell using this style (if set) */
-    const Cell* GetUsingCell() const { return mpUsingCell; }
-
     bool operator==( const Style& rOther) const;
     bool operator<( const Style& rOther) const;
 };
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index 2b06d29a41b2..e135e371319c 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -291,8 +291,7 @@ public:
 
     /** Returns the output range of the cell (nCol,nRow).
         Returns total output range of merged ranges. */
-    basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow ) const;
-    basegfx::B2DRange GetCellRange( size_t nCellIndex ) const;
+    basegfx::B2DRange GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const;
 
     // mirroring --------------------------------------------------------------
 
@@ -312,9 +311,6 @@ public:
     /** Draws the part of the array, that is inside the clipping range. */
     drawinglayer::primitive2d::Primitive2DContainer CreateB2DPrimitiveArray() const;
 
-    // fill the Cell::maCellIndex entries to allow referencing back from Cell to Array Col/Row coordinates
-    void AddCellIndices() const;
-
 private:
     std::unique_ptr<ArrayImpl>        mxImpl;
 };
diff --git a/sc/source/ui/miscdlgs/autofmt.cxx b/sc/source/ui/miscdlgs/autofmt.cxx
index a6ffdfe75389..f8f2dae645a6 100644
--- a/sc/source/ui/miscdlgs/autofmt.cxx
+++ b/sc/source/ui/miscdlgs/autofmt.cxx
@@ -250,7 +250,7 @@ void ScAutoFmtPreview::DrawString(vcl::RenderContext& rRenderContext, size_t nCo
 
         Size aStrSize;
         sal_uInt16 nFmtIndex = GetFormatIndex( nCol, nRow );
-        const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow ));
+        const basegfx::B2DRange cellRange(maArray.GetCellRange( nCol, nRow, true ));
         Point aPos = Point(basegfx::fround(cellRange.getMinX()), basegfx::fround(cellRange.getMinY()));
         sal_uInt16 nRightX = 0;
         bool bJustify = pCurData->GetIncludeJustify();
@@ -374,7 +374,7 @@ void ScAutoFmtPreview::DrawBackground(vcl::RenderContext& rRenderContext)
                 rRenderContext.SetLineColor();
                 rRenderContext.SetFillColor( pItem->GetColor() );
 
-                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
                 rRenderContext.DrawRect(
                     tools::Rectangle(
                         basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 1501fca0022d..269ac3e52e49 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -51,14 +51,12 @@ void Style::implEnsureImplStyle()
 }
 
 Style::Style() :
-    maImplStyle(),
-    mpUsingCell(nullptr)
+    maImplStyle()
 {
 }
 
 Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
-    maImplStyle(new implStyle()),
-    mpUsingCell(nullptr)
+    maImplStyle(new implStyle())
 {
     maImplStyle->mnType = nType;
     maImplStyle->mfPatternScale = fScale;
@@ -66,8 +64,7 @@ Style::Style( double nP, double nD, double nS, SvxBorderLineStyle nType, double
 }
 
 Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS, SvxBorderLineStyle nType, double fScale ) :
-    maImplStyle(new implStyle()),
-    mpUsingCell(nullptr)
+    maImplStyle(new implStyle())
 {
     maImplStyle->mnType = nType;
     maImplStyle->mfPatternScale = fScale;
@@ -75,8 +72,7 @@ Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rCo
 }
 
 Style::Style( const editeng::SvxBorderLine* pBorder, double fScale ) :
-    maImplStyle(),
-    mpUsingCell(nullptr)
+    maImplStyle()
 {
     if(nullptr != pBorder)
     {
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index 560eefd775ce..ecb3eaace1c6 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -45,10 +45,8 @@ public:
     long                mnAddTop;
     long                mnAddBottom;
 
-    SvxRotateMode           meRotMode;
-    double                  mfOrientation;
-    basegfx::B2DHomMatrix   maCoordinateSystem;
-    size_t                  maCellIndex;
+    SvxRotateMode       meRotMode;
+    double              mfOrientation;
 
     bool                mbMergeOrig;
     bool                mbOverlapX;
@@ -57,12 +55,12 @@ public:
 public:
     explicit            Cell();
 
-    void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; maLeft.SetUsingCell(this); }
-    void SetStyleRight(const Style& rStyle) { maRight = rStyle; maRight.SetUsingCell(this); }
-    void SetStyleTop(const Style& rStyle) { maTop = rStyle; maTop.SetUsingCell(this); }
-    void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; maBottom.SetUsingCell(this); }
-    void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; maTLBR.SetUsingCell(this); }
-    void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; maBLTR.SetUsingCell(this); }
+    void SetStyleLeft(const Style& rStyle) { maLeft = rStyle; }
+    void SetStyleRight(const Style& rStyle) { maRight = rStyle; }
+    void SetStyleTop(const Style& rStyle) { maTop = rStyle; }
+    void SetStyleBottom(const Style& rStyle) { maBottom = rStyle; }
+    void SetStyleTLBR(const Style& rStyle) { maTLBR = rStyle; }
+    void SetStyleBLTR(const Style& rStyle) { maBLTR = rStyle; }
 
     const Style& GetStyleLeft() const { return maLeft; }
     const Style& GetStyleRight() const { return maRight; }
@@ -76,74 +74,54 @@ public:
 
     void                MirrorSelfX();
 
-    basegfx::B2DHomMatrix const & CreateCoordinateSystem(const Array& rArray) const;
-    size_t GetCellIndex(const Array& rArray) const;
+    basegfx::B2DHomMatrix CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const;
 };
 
 typedef std::vector< long >     LongVec;
 typedef std::vector< Cell >     CellVec;
 
-size_t Cell::GetCellIndex(const Array& rArray) const
+basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray, size_t nCol, size_t nRow, bool bExpandMerged) const
 {
-    if(static_cast<size_t>(-1) == maCellIndex)
-    {
-        rArray.AddCellIndices();
-    }
-
-    return maCellIndex;
-}
+    basegfx::B2DHomMatrix aRetval;
+    const basegfx::B2DRange aRange(rArray.GetCellRange(nCol, nRow, bExpandMerged));
 
-basegfx::B2DHomMatrix const & Cell::CreateCoordinateSystem(const Array& rArray) const
-{
-    if(!maCoordinateSystem.isIdentity())
+    if(!aRange.isEmpty())
     {
-        return maCoordinateSystem;
-    }
-
-    const size_t nCellIndex(GetCellIndex(rArray));
+        basegfx::B2DPoint aOrigin(aRange.getMinimum());
+        basegfx::B2DVector aX(aRange.getWidth(), 0.0);
+        basegfx::B2DVector aY(0.0, aRange.getHeight());
 
-    if(static_cast<size_t>(-1) != nCellIndex)
-    {
-        const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex));
-
-        if(!aRange.isEmpty())
+        if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
         {
-            basegfx::B2DPoint aOrigin(aRange.getMinimum());
-            basegfx::B2DVector aX(aRange.getWidth(), 0.0);
-            basegfx::B2DVector aY(0.0, aRange.getHeight());
+            // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
+            const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
 
-            if (IsRotated() && SvxRotateMode::SVX_ROTATE_MODE_STANDARD != meRotMode)
+            switch (meRotMode)
             {
-                // when rotated, adapt values. Get Skew (cos/sin == 1/tan)
-                const double fSkew(aY.getY() * (cos(mfOrientation) / sin(mfOrientation)));
-
-                switch (meRotMode)
-                {
-                case SvxRotateMode::SVX_ROTATE_MODE_TOP:
-                    // shear Y-Axis
-                    aY.setX(-fSkew);
-                    break;
-                case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
-                    // shear origin half, Y full
-                    aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
-                    aY.setX(-fSkew);
-                    break;
-                case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
-                    // shear origin full, Y full
-                    aOrigin.setX(aOrigin.getX() + fSkew);
-                    aY.setX(-fSkew);
-                    break;
-                default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
-                    break;
-                }
+            case SvxRotateMode::SVX_ROTATE_MODE_TOP:
+                // shear Y-Axis
+                aY.setX(-fSkew);
+                break;
+            case SvxRotateMode::SVX_ROTATE_MODE_CENTER:
+                // shear origin half, Y full
+                aOrigin.setX(aOrigin.getX() + (fSkew * 0.5));
+                aY.setX(-fSkew);
+                break;
+            case SvxRotateMode::SVX_ROTATE_MODE_BOTTOM:
+                // shear origin full, Y full
+                aOrigin.setX(aOrigin.getX() + fSkew);
+                aY.setX(-fSkew);
+                break;
+            default: // SvxRotateMode::SVX_ROTATE_MODE_STANDARD, already excluded above
+                break;
             }
-
-            // use column vectors as coordinate axes, homogen column for translation
-            const_cast<Cell*>(this)->maCoordinateSystem = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
         }
+
+        // use column vectors as coordinate axes, homogen column for translation
+        aRetval = basegfx::utils::createCoordinateSystemTransform(aOrigin, aX, aY);
     }
 
-    return maCoordinateSystem;
+    return aRetval;
 }
 
 Cell::Cell() :
@@ -153,8 +131,6 @@ Cell::Cell() :
     mnAddBottom( 0 ),
     meRotMode(SvxRotateMode::SVX_ROTATE_MODE_STANDARD ),
     mfOrientation( 0.0 ),
-    maCoordinateSystem(),
-    maCellIndex(static_cast<size_t>(-1)),
     mbMergeOrig( false ),
     mbOverlapX( false ),
     mbOverlapY( false )
@@ -168,8 +144,6 @@ void Cell::MirrorSelfX()
     maLeft.MirrorSelf();
     maRight.MirrorSelf();
     mfOrientation = -mfOrientation;
-    maCoordinateSystem.identity();
-    maCellIndex = static_cast<size_t>(-1);
 }
 
 
@@ -864,17 +838,12 @@ long Array::GetHeight() const
     return GetRowPosition( mxImpl->mnHeight ) - GetRowPosition( 0 );
 }
 
-basegfx::B2DRange Array::GetCellRange( size_t nCellIndex ) const
-{
-    return GetCellRange(nCellIndex % GetColCount(), nCellIndex / GetColCount());
-}
-
-basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow ) const
+basegfx::B2DRange Array::GetCellRange( size_t nCol, size_t nRow, bool bExpandMerged ) const
 {
-    size_t nFirstCol = mxImpl->GetMergedFirstCol( nCol, nRow );
-    size_t nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow );
-    size_t nLastCol = mxImpl->GetMergedLastCol( nCol, nRow );
-    size_t nLastRow = mxImpl->GetMergedLastRow( nCol, nRow );
+    size_t nFirstCol = bExpandMerged ? mxImpl->GetMergedFirstCol( nCol, nRow ) : nCol;
+    size_t nFirstRow = bExpandMerged ? mxImpl->GetMergedFirstRow( nCol, nRow ) : nRow;
+    size_t nLastCol = bExpandMerged ? mxImpl->GetMergedLastCol( nCol, nRow ) : nCol;
+    size_t nLastRow = bExpandMerged ? mxImpl->GetMergedLastRow( nCol, nRow ) : nRow;
     const Point aPoint( GetColPosition( nFirstCol ), GetRowPosition( nFirstRow ) );
     const Size aSize( GetColWidth( nFirstCol, nLastCol ) + 1, GetRowHeight( nFirstRow, nLastRow ) + 1 );
     tools::Rectangle aRect(aPoint, aSize);
@@ -1023,45 +992,6 @@ void HelperCreateVerticalEntry(
     );
 }
 
-void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::primitive2d::Primitive2DContainer& rSequence, const Color* pForceColor)
-{
-    const Cell* pCell = rStyle.GetUsingCell();
-
-    if(nullptr != pCell)
-    {
-        const size_t nCellIndex(pCell->GetCellIndex(rArray));
-
-        if(static_cast<size_t>(-1) != nCellIndex)
-        {
-            size_t col(nCellIndex % rArray.GetColCount());
-            size_t row(nCellIndex / rArray.GetColCount());
-            const bool bL(&rStyle == &pCell->GetStyleLeft());
-            const bool bR(&rStyle == &pCell->GetStyleRight());
-            const bool bT(&rStyle == &pCell->GetStyleTop());
-            const bool bB(&rStyle == &pCell->GetStyleBottom());
-
-            if(bL || bR || bT || bB)
-            {
-                const basegfx::B2DHomMatrix aCoordinateSystem(pCell->CreateCoordinateSystem(rArray));
-                const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
-                const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
-                const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
-                if(bL || bR)
-                {
-                    // left/right
-                    HelperCreateVerticalEntry(rArray, rStyle, bL ? col : col + 1, row, aOrigin, aX, aY, rSequence, bL, pForceColor);
-                }
-                else if(bT || bB)
-                {
-                    // top/bottom
-                    HelperCreateHorizontalEntry(rArray, rStyle, col, bT ? row : row + 1, aOrigin, aX, aY, rSequence, bT, pForceColor);
-                }
-            }
-        }
-    }
-}
-
 void HelperMergeInB2DPrimitiveArray(
     const drawinglayer::primitive2d::Primitive2DContainer& rSource,
     drawinglayer::primitive2d::Primitive2DContainer& rTarget)
@@ -1116,23 +1046,27 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1);
     drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
 
+    // remember for which merged cells crossed lines were already created. To
+    // do so, hold the size_t cell index in a set for fast check
+    std::set< size_t > aMergedCells;
+
     for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow)
     {
         for (size_t nCol = nFirstCol; nCol <= nLastCol; ++nCol)
         {
+            // get Cell and CoordinateSystem (*only* for this Cell), check if used (not empty)
             const Cell& rCell = CELL(nCol, nRow);
-            const basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this));
-            const basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
-            const basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
+            basegfx::B2DHomMatrix aCoordinateSystem(rCell.CreateCoordinateSystem(*this, nCol, nRow, false));
+            basegfx::B2DVector aX(basegfx::utils::getColumn(aCoordinateSystem, 0));
+            basegfx::B2DVector aY(basegfx::utils::getColumn(aCoordinateSystem, 1));
 
             if(!aX.equalZero() && !aY.equalZero())
             {
-                size_t _nFirstCol = mxImpl->GetMergedFirstCol(nCol, nRow);
-                size_t _nFirstRow = mxImpl->GetMergedFirstRow(nCol, nRow);
-                size_t _nLastCol = mxImpl->GetMergedLastCol(nCol, nRow);
-                size_t _nLastRow = mxImpl->GetMergedLastRow(nCol, nRow);
-                const basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
-
+                // for getting correct Style(s) for merged Cells, we need the First(Col/Row)
+                // for access (see accessing Styles below)
+                const size_t _nFirstCol(mxImpl->GetMergedFirstCol(nCol, nRow));
+                const size_t _nFirstRow(mxImpl->GetMergedFirstRow(nCol, nRow));
+                basegfx::B2DPoint aOrigin(basegfx::utils::getColumn(aCoordinateSystem, 2));
                 const bool bOverlapX(rCell.mbOverlapX);
                 const bool bOverlapY(rCell.mbOverlapY);
                 const bool bFirstCol(nCol == nFirstCol);
@@ -1140,116 +1074,152 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
                 const bool bFirstRow(nRow == nFirstRow);
                 const bool bLastRow(nRow == nLastRow);
 
-                if (!bOverlapX || bFirstRow)
+                // create upper line for this Cell
+                if (!bOverlapY      // true for first line in merged cells or cells
+                    || bFirstRow)   // true for non_Calc usages of this tooling
                 {
                     const Style& rTop = GetCellStyleTop(_nFirstCol, _nFirstRow);
 
                     if(rTop.IsUsed())
                     {
-                        HelperCreateEntry(*this, rTop, aHorizontalSequence, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, aHorizontalSequence, true, pForceColor);
                     }
                 }
 
-                if (bLastRow)
+                // create lower line for this Cell
+                if (bLastRow)       // true for non_Calc usages of this tooling
                 {
                     const Style& rBottom = GetCellStyleBottom(_nFirstCol, _nFirstRow);
 
                     if(rBottom.IsUsed())
                     {
-                        HelperCreateEntry(*this, rBottom, aHorizontalSequence, pForceColor);
+                        HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, aHorizontalSequence, false, pForceColor);
                     }
                 }
 
-                if (!bOverlapY || bFirstCol)
+                // create left line for this Cell
+                if (!bOverlapX      // true for first column in merged cells or cells
+                    || bFirstCol)   // true for non_Calc usages of this tooling
                 {
                     const Style& rLeft(GetCellStyleLeft(_nFirstCol, _nFirstRow));
 
                     if(rLeft.IsUsed())
                     {
-                        HelperCreateEntry(*this, rLeft, aVerticalSequences[nCol - nFirstCol], pForceColor);
+                        HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], true, pForceColor);
                     }
                 }
 
-                if (bLastCol)
+                // create right line for this Cell
+                if (bLastCol)       // true for non_Calc usages of this tooling
                 {
                     const Style& rRight(GetCellStyleRight(_nFirstCol, _nFirstRow));
 
                     if(rRight.IsUsed())
                     {
-                        HelperCreateEntry(*this, rRight, aVerticalSequences[nCol - nFirstCol], pForceColor);
+                        HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nFirstCol], false, pForceColor);
                     }
                 }
 
-                if ((!bOverlapX && !bOverlapY) || (bFirstCol && bFirstRow) || (!bOverlapY && bFirstCol) || (!bOverlapX && bFirstRow))
+                // check for crossed lines, these need special treatment, especially
+                // for merged cells, see below
+                const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
+                const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
+
+                if(rTLBR.IsUsed() || rBLTR.IsUsed())
                 {
-                    const Style& rTLBR = GetCellStyleTLBR(_nFirstCol, _nFirstRow);
-                    if(rTLBR.IsUsed())
+                    bool bContinue(true);
+
+                    if(rCell.IsMerged())
                     {
-                        /// top-left and bottom-right Style Tables
-                        /// Fill top-left Style Table
-                        const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
-                        const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
-                        StyleVectorTable aStart;
-                        const basegfx::B2DVector aAxisA(aX + aY);
-
-                        aStart.add(rTLFromRight, aAxisA, aX, false);
-                        aStart.add(rTLFromBottom, aAxisA, aY, false);
-                        aStart.sort();
-
-                        /// Fill bottom-right Style Table
-                        const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
-                        const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
-                        StyleVectorTable aEnd;
-                        const basegfx::B2DVector aAxisB(-aX -aY);
-
-                        aEnd.add(rBRFromBottom, aAxisB, -aY, true);
-                        aEnd.add(rBRFromLeft, aAxisB, -aX, true);
-                        aEnd.sort();
-
-                        CreateBorderPrimitives(
-                            aCrossSequence,
-                            aOrigin,
-                            aX + aY,
-                            rTLBR,
-                            aStart,
-                            aEnd,
-                            pForceColor
-                        );
+                        // first check if this merged cell was already handled
+                        const size_t nIndexOfMergedCell(mxImpl->GetIndex(_nFirstCol, _nFirstRow));
+                        bContinue = (aMergedCells.end() == aMergedCells.find(nIndexOfMergedCell));
+
+                        if(bContinue)
+                        {
+                            // not found, add now to mark as handled
+                            aMergedCells.insert(nIndexOfMergedCell);
+
+                            // when merged, get extended coordinate system and dependent values
+                            aCoordinateSystem = rCell.CreateCoordinateSystem(*this, nCol, nRow, true);
+                            aX = basegfx::utils::getColumn(aCoordinateSystem, 0);
+                            aY = basegfx::utils::getColumn(aCoordinateSystem, 1);
+                            aOrigin = basegfx::utils::getColumn(aCoordinateSystem, 2);
+                        }
                     }
 
-                    const Style& rBLTR = GetCellStyleBLTR(_nFirstCol, _nFirstRow);
-                    if(rBLTR.IsUsed())
+                    if(bContinue)
                     {
-                        /// bottom-left and top-right Style Tables
-                        /// Fill bottom-left Style Table
-                        const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
-                        const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
-                        StyleVectorTable aStart;
-                        const basegfx::B2DVector aAxisA(aX - aY);
-
-                        aStart.add(rBLFromTop, aAxisA, -aY, true);
-                        aStart.add(rBLFromBottom, aAxisA, aX, false);
-                        aStart.sort();
-
-                        /// Fill top-right Style Table
-                        const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
-                        const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
-                        StyleVectorTable aEnd;
-                        const basegfx::B2DVector aAxisB(aY - aX);
-
-                        aEnd.add(rTRFromLeft, aAxisB, -aX, true);
-                        aEnd.add(rTRFromBottom, aAxisB, aY, false);
-                        aEnd.sort();
-
-                        CreateBorderPrimitives(
-                            aCrossSequence,
-                            aOrigin + aY,
-                            aX - aY,
-                            rBLTR,
-                            aStart,
-                            aEnd,
-                            pForceColor
-                        );
+                        const size_t _nLastCol(mxImpl->GetMergedLastCol(nCol, nRow));
+                        const size_t _nLastRow(mxImpl->GetMergedLastRow(nCol, nRow));
+
+                        if(rTLBR.IsUsed())
+                        {
+                            /// top-left and bottom-right Style Tables
+                            /// Fill top-left Style Table
+                            const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow));
+                            const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow));
+                            StyleVectorTable aStart;
+                            const basegfx::B2DVector aAxisA(aX + aY);
+
+                            aStart.add(rTLFromRight, aAxisA, aX, false);
+                            aStart.add(rTLFromBottom, aAxisA, aY, false);
+                            aStart.sort();
+
+                            /// Fill bottom-right Style Table
+                            const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow));
+                            const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow));
+                            StyleVectorTable aEnd;
+                            const basegfx::B2DVector aAxisB(-aX -aY);
+
+                            aEnd.add(rBRFromBottom, aAxisB, -aY, true);
+                            aEnd.add(rBRFromLeft, aAxisB, -aX, true);
+                            aEnd.sort();
+
+                            CreateBorderPrimitives(
+                                aCrossSequence,
+                                aOrigin,
+                                aX + aY,
+                                rTLBR,
+                                aStart,
+                                aEnd,
+                                pForceColor
+                            );
+                        }
+
+                        if(rBLTR.IsUsed())
+                        {
+                            /// bottom-left and top-right Style Tables
+                            /// Fill bottom-left Style Table
+                            const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow));
+                            const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow));
+                            StyleVectorTable aStart;
+                            const basegfx::B2DVector aAxisA(aX - aY);
+
+                            aStart.add(rBLFromTop, aAxisA, -aY, true);
+                            aStart.add(rBLFromBottom, aAxisA, aX, false);
+                            aStart.sort();
+
+                            /// Fill top-right Style Table
+                            const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow));
+                            const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow));
+                            StyleVectorTable aEnd;
+                            const basegfx::B2DVector aAxisB(aY - aX);
+
+                            aEnd.add(rTRFromLeft, aAxisB, -aX, true);
+                            aEnd.add(rTRFromBottom, aAxisB, aY, false);
+                            aEnd.sort();
+
+                            CreateBorderPrimitives(
+                                aCrossSequence,
+                                aOrigin + aY,
+                                aX - aY,
+                                rBLTR,
+                                aStart,
+                                aEnd,
+                                pForceColor
+                            );
+                        }
                     }
                 }
             }
@@ -1259,6 +1229,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
     // to stay compatible, create order as it was formally. Also try to
     // merge primitives as far as possible
     HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence);
+
     for(const auto& aVert : aVerticalSequences)
     {
         HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence);
@@ -1279,19 +1250,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray()
     return aPrimitives;
 }
 
-void Array::AddCellIndices() const
-{
-    for (size_t a(0); a < mxImpl->maCells.size(); a++)
-    {
-        const_cast<Array*>(this)->mxImpl->maCells[a].maCellIndex = a;
-    }
-}
-
 #undef ORIGCELL
 #undef CELLACC
 #undef CELL
-
-
 #undef DBG_FRAME_CHECK_ROW_1
 #undef DBG_FRAME_CHECK_COL_1
 #undef DBG_FRAME_CHECK_COLROW
@@ -1299,7 +1260,6 @@ void Array::AddCellIndices() const
 #undef DBG_FRAME_CHECK_COL
 #undef DBG_FRAME_CHECK
 
-
 }
 }
 
diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx
index d54e1b083e65..f65693d44b58 100644
--- a/svx/source/dialog/frmsel.cxx
+++ b/svx/source/dialog/frmsel.cxx
@@ -410,7 +410,7 @@ void FrameSelectorImpl::InitBorderGeometry()
     {
         for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
         {
-            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
             const tools::Rectangle aRect(
                 basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
                 basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -469,7 +469,7 @@ void FrameSelectorImpl::InitBorderGeometry()
             for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
             {
                 // the usable area between horizonal/vertical frame borders of current quadrant
-                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+                const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
                 const tools::Rectangle aRect(
                     basegfx::fround(aCellRange.getMinX()) + nClV + 1, basegfx::fround(aCellRange.getMinY()) + nClH + 1,
                     basegfx::fround(aCellRange.getMaxX()) - nClV + 1, basegfx::fround(aCellRange.getMaxY()) - nClH + 1);
diff --git a/sw/source/ui/table/tautofmt.cxx b/sw/source/ui/table/tautofmt.cxx
index 7a342f1ff83e..5336024736fa 100644
--- a/sw/source/ui/table/tautofmt.cxx
+++ b/sw/source/ui/table/tautofmt.cxx
@@ -716,7 +716,7 @@ MAKENUMSTR:
     SvtScriptedTextHelper aScriptedText(rRenderContext);
     Size aStrSize;
     sal_uInt8 nFormatIndex = GetFormatIndex( nCol, nRow );
-    const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+    const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
     const tools::Rectangle cellRect(
         basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
         basegfx::fround(aCellRange.getMaxX()), basegfx::fround(aCellRange.getMaxY()));
@@ -811,7 +811,7 @@ void AutoFormatPreview::DrawBackground(vcl::RenderContext& rRenderContext)
             rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
             rRenderContext.SetLineColor();
             rRenderContext.SetFillColor(aBrushItem.GetColor());
-            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow ));
+            const basegfx::B2DRange aCellRange(maArray.GetCellRange( nCol, nRow, true ));
             rRenderContext.DrawRect(
                 tools::Rectangle(
                     basegfx::fround(aCellRange.getMinX()), basegfx::fround(aCellRange.getMinY()),
commit 2d8f17565ebe867210f5769851d91b2e7b612a8f
Author: Jim Raykowski <raykowj at gmail.com>
Date:   Sat Dec 30 16:38:29 2017 -0900

    tdf#114771 make focus rect in Navigator content tree position correctly
    
    Change-Id: I747d3ef2bbe7227b048e29bd8c5758fb7778ab9d
    Reviewed-on: https://gerrit.libreoffice.org/48738
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Tamás Zolnai <tamas.zolnai at collabora.com>

diff --git a/sw/source/uibase/utlui/content.cxx b/sw/source/uibase/utlui/content.cxx
index df7f1bbb29c1..489073d55341 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1763,6 +1763,7 @@ void SwContentTree::Display( bool bActive )
                     {
                         MakeVisible(pEntry);
                         Select(pEntry);
+                        SetCurEntry(pEntry);
                     }
                 }
 
commit 99d08aa87b945f909d0d0439e2f636918b0b858d
Author: Justin Luth <justin_luth at sil.org>
Date:   Wed Jan 17 12:36:39 2018 +0300

    writerfilter: FindStyleSheetBy... remove StyleName option
    
    It is confusing having three undocumented Find functions.
    Reduce by one - either search on the imported WW8 (ISTD) name
    or on the internal (converted) name.
    
    The one remaining use of ByStyleName was testing against an
    already set property, so by definition it was set using
    convertedStyleName.  (Plus, that was my code anyway...)
    
    Change-Id: If5a352bedb7d297698f449fbb629a1350e27c51c
    Reviewed-on: https://gerrit.libreoffice.org/48037
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Justin Luth <justin_luth at sil.org>

diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index a573275a338b..464910fb625c 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2546,7 +2546,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
                 OUString sStyleName;
                 pParagraphProps->getProperty(PROP_PARA_STYLE_NAME)->second >>= sStyleName;
                 if( !sStyleName.isEmpty() && GetStyleSheetTable() )
-                    pStyle = GetStyleSheetTable()->FindStyleSheetByStyleName( sStyleName );
+                    pStyle = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName( sStyleName );
 
                 if( pStyle && pStyle->pProperties
                     && pStyle->pProperties->isSet(PROP_BREAK_TYPE)
diff --git a/writerfilter/source/dmapper/StyleSheetTable.cxx b/writerfilter/source/dmapper/StyleSheetTable.cxx
index 7c52ef505aef..433405feabf4 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.cxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.cxx
@@ -1247,21 +1247,6 @@ const StyleSheetEntryPtr StyleSheetTable::FindStyleSheetByISTD(const OUString& s
 }
 
 
-const StyleSheetEntryPtr StyleSheetTable::FindStyleSheetByStyleName(const OUString& sIndex)
-{
-    StyleSheetEntryPtr pRet;
-    for(StyleSheetEntryPtr & rpEntry : m_pImpl->m_aStyleSheetEntries)
-    {
-        if( rpEntry->sStyleName == sIndex)
-        {
-            pRet = rpEntry;
-            break;
-        }
-    }
-    return pRet;
-}
-
-
 const StyleSheetEntryPtr StyleSheetTable::FindStyleSheetByConvertedStyleName(const OUString& sIndex)
 {
     StyleSheetEntryPtr pRet;
diff --git a/writerfilter/source/dmapper/StyleSheetTable.hxx b/writerfilter/source/dmapper/StyleSheetTable.hxx
index 933a6e20fd85..767a16af3dfb 100644
--- a/writerfilter/source/dmapper/StyleSheetTable.hxx
+++ b/writerfilter/source/dmapper/StyleSheetTable.hxx
@@ -91,7 +91,6 @@ public:
 
     void ApplyStyleSheets( const FontTablePtr& rFontTable );
     const StyleSheetEntryPtr FindStyleSheetByISTD(const OUString& sIndex);
-    const StyleSheetEntryPtr FindStyleSheetByStyleName(const OUString& rIndex);
     const StyleSheetEntryPtr FindStyleSheetByConvertedStyleName(const OUString& rIndex);
     const StyleSheetEntryPtr FindDefaultParaStyle();
     // returns the parent of the one with the given name - if empty the parent of the current style sheet is returned
commit 769af98f887a742261886f960212d9d3f581e973
Author: Justin Luth <justin_luth at sil.org>
Date:   Wed Jan 17 21:40:57 2018 +0300

    mailconfig: default to secure port 587
    
    A very readable explanation of ports 25 / 465 / 587 was
    http://blog.mailgun.com/25-465-587-what-port-should-i-use/
    
    In short, 465 was a very temporary and never official port
    to use for encrypted sending. Port 587 is the official
    port for encrypted (or even non-encrypted) mail submissions.
    
    For a very long time now, every public mail server (and likely
    even private internal servers) supports STARTTLS, so default
    to using secure connections.
    
    Change-Id: Ic8a6886221fa2e7b733b2535a84a584fe64d3165
    Reviewed-on: https://gerrit.libreoffice.org/48075
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Heiko Tietze <tietze.heiko at gmail.com>
    Tested-by: Heiko Tietze <tietze.heiko at gmail.com>
    Reviewed-by: Jan-Marek Glogowski <glogow at fbihome.de>
    Reviewed-by: Justin Luth <justin_luth at sil.org>

diff --git a/sw/source/uibase/dbui/mmconfigitem.cxx b/sw/source/uibase/dbui/mmconfigitem.cxx
index 957d65474724..92fbccf8381d 100644
--- a/sw/source/uibase/dbui/mmconfigitem.cxx
+++ b/sw/source/uibase/dbui/mmconfigitem.cxx
@@ -59,7 +59,7 @@ const char cDataSourceName[]         = "DataSource/DataSourceName";
 const char cDataTableName[]          = "DataSource/DataTableName" ;
 const char cDataCommandType[]        = "DataSource/DataCommandType";
 
-#define SECURE_PORT     465
+#define SECURE_PORT     587
 #define DEFAULT_PORT    25
 #define POP_PORT        110
 
@@ -196,7 +196,7 @@ SwMailMergeConfigItem_Impl::SwMailMergeConfigItem_Impl() :
         m_nMailPort(0),
         m_bIsMailReplyTo(false),
         m_bIsDefaultPort(false),
-        m_bIsSecureConnection(false),
+        m_bIsSecureConnection(true),
         m_bIsAuthentication(false),
 
         m_bIsEMailSupported(false),
commit 8c993d963714b861cb39c8249cb6e782bb144739
Author: Dmitri Kharchev <dh_twriter at mail.ru>
Date:   Sat Jan 27 08:07:58 2018 -0200

    Updated core
    Project: help  f244829556e67657cdd5c08d4126151b067a2a15
    
    tdf#100810 CEILING.XCL, CEILING.MATH not in help
    
    Change-Id: I94325c24e5e34db2a6d44d6124cd2e44cb76d201
    Signed-off-by: Olivier Hallot <olivier.hallot at libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/48743

diff --git a/helpcontent2 b/helpcontent2
index 9bd1736a8b3d..f244829556e6 160000
--- a/helpcontent2
+++ b/helpcontent2
@@ -1 +1 @@
-Subproject commit 9bd1736a8b3dc0631e14b12fd81ba4136e8aaa99
+Subproject commit f244829556e67657cdd5c08d4126151b067a2a15
commit 3a68b21c212c1c2fc7f1d8f4d1abc8990bcd91c0
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Fri Jan 26 20:28:46 2018 +0100

    lok: Allow whitelisting languages that should be used by LibreOfficeKit.
    
    LOK may get way too many languages if there are dictionaries for them
    installed which blows the pre-init to >2G easily; let's allow limiting that.
    
    Also make the preloading of languages work with the internal spell checking
    dictionaries and thesauri.
    
    Change-Id: I77119970030a7386a5cccbe4fdc89b15eab56ef1
    Reviewed-on: https://gerrit.libreoffice.org/48720
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx
index 2e8624d1e8d0..589f57b61bce 100644
--- a/comphelper/source/misc/lok.cxx
+++ b/comphelper/source/misc/lok.cxx
@@ -9,6 +9,8 @@
 
 #include <comphelper/lok.hxx>
 
+#include <iostream>
+
 namespace comphelper
 {
 
@@ -112,6 +114,52 @@ const LanguageTag& getLanguageTag()
     return g_aLanguageTag;
 }
 
+bool isWhitelistedLanguage(const OUString& lang)
+{
+    if (!isActive())
+        return true;
+
+    static bool bInitialized = false;
+    static std::vector<OUString> aWhitelist;
+    if (!bInitialized)
+    {
+        const char* pWhitelist = getenv("LOK_WHITELIST_LANGUAGES");
+        if (pWhitelist)
+        {
+            std::stringstream stream(pWhitelist);
+            std::string s;
+
+            std::cerr << "Whitelisted languages: ";
+            while (getline(stream, s, ' ')) {
+                if (s.length() == 0)
+                    continue;
+
+                std::cerr << s << " ";
+                aWhitelist.emplace_back(OStringToOUString(s.c_str(), RTL_TEXTENCODING_UTF8));
+            }
+            std::cerr << std::endl;
+        }
+
+        if (aWhitelist.empty())
+            std::cerr << "No language whitelisted, turning off the language support." << std::endl;
+
+        bInitialized = true;
+    }
+
+    if (aWhitelist.empty())
+        return false;
+
+    for (auto& entry : aWhitelist)
+    {
+        if (lang.startsWith(entry))
+            return true;
+        if (lang.startsWith(entry.replace('_', '-')))
+            return true;
+    }
+
+    return false;
+}
+
 static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent)(nullptr);
 static void *pStatusIndicatorCallbackData(nullptr);
 
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index deba56c3eafc..54f81663517b 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -3720,7 +3720,7 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
     if (eStage != PRE_INIT)
         comphelper::LibreOfficeKit::setStatusIndicatorCallback(lo_status_indicator_callback, pLib);
 
-    if (pUserProfileUrl)
+    if (pUserProfileUrl && eStage != PRE_INIT)
     {
         OUString url(
             pUserProfileUrl, strlen(pUserProfileUrl), RTL_TEXTENCODING_UTF8);
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index e9634e77d6f9..9759bb524541 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -71,6 +71,8 @@ COMPHELPER_DLLPUBLIC bool isRangeHeaders();
 COMPHELPER_DLLPUBLIC void setLanguageTag(const LanguageTag& languageTag);
 /// Get the current LOK's language.
 COMPHELPER_DLLPUBLIC const LanguageTag& getLanguageTag();
+/// If the language name should be used for this LOK instance.
+COMPHELPER_DLLPUBLIC bool isWhitelistedLanguage(const OUString& lang);
 
 // Status indicator handling. Even if in theory there could be several status indicators active at
 // the same time, in practice there is only one at a time, so we don't handle any identification of
diff --git a/lingucomponent/source/spellcheck/spell/sspellimp.cxx b/lingucomponent/source/spellcheck/spell/sspellimp.cxx
index 694bc1aa27e4..12b9e240fa24 100644
--- a/lingucomponent/source/spellcheck/spell/sspellimp.cxx
+++ b/lingucomponent/source/spellcheck/spell/sspellimp.cxx
@@ -20,6 +20,7 @@
 #include <com/sun/star/uno/Reference.h>
 
 #include <com/sun/star/linguistic2/SpellFailure.hpp>
+#include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
 #include <cppuhelper/factory.hxx>
 #include <cppuhelper/supportsservice.hxx>
@@ -156,6 +157,9 @@ Sequence< Locale > SAL_CALL SpellChecker::getLocales()
                     {
                         for (auto const& locale : aLocaleNames)
                         {
+                            if (!comphelper::LibreOfficeKit::isWhitelistedLanguage(locale))
+                                continue;
+
                             aLocaleNamesSet.insert(locale);
                         }
                     }
diff --git a/lingucomponent/source/thesaurus/libnth/nthesimp.cxx b/lingucomponent/source/thesaurus/libnth/nthesimp.cxx
index 88a6550ddf5e..ce1d4a07f492 100644
--- a/lingucomponent/source/thesaurus/libnth/nthesimp.cxx
+++ b/lingucomponent/source/thesaurus/libnth/nthesimp.cxx
@@ -26,6 +26,7 @@
 #include <com/sun/star/linguistic2/XSpellChecker1.hpp>
 #include <i18nlangtag/languagetag.hxx>
 #include <tools/debug.hxx>
+#include <comphelper/lok.hxx>
 #include <comphelper/processfactory.hxx>
 #include <osl/mutex.hxx>
 #include <unotools/pathoptions.hxx>
@@ -174,6 +175,9 @@ Sequence< Locale > SAL_CALL Thesaurus::getLocales()
                 sal_Int32 nLen2 = aLocaleNames.getLength();
                 for (k = 0;  k < nLen2;  ++k)
                 {
+                    if (!comphelper::LibreOfficeKit::isWhitelistedLanguage(aLocaleNames[k]))
+                        continue;
+
                     aLocaleNamesSet.insert( aLocaleNames[k] );
                 }
             }
commit 079775c0d52a49cef5e22790149ad97747c1e940
Author: Andrea Gelmini <andrea.gelmini at gelma.net>
Date:   Fri Jan 26 15:19:08 2018 +0100

    Updated core
    Project: help  9bd1736a8b3dc0631e14b12fd81ba4136e8aaa99
    
    Fix typos
    
    Change-Id: I1c9a02aab47a26a9f18d2327ca0f4f58adac2c0d
    Reviewed-on: https://gerrit.libreoffice.org/48695
    Reviewed-by: Julien Nabet <serval2412 at yahoo.fr>
    Tested-by: Julien Nabet <serval2412 at yahoo.fr>

diff --git a/helpcontent2 b/helpcontent2
index 5be1429f1ad6..9bd1736a8b3d 160000
--- a/helpcontent2
+++ b/helpcontent2
@@ -1 +1 @@
-Subproject commit 5be1429f1ad6ac472836097516ab3cd0681ecf38
+Subproject commit 9bd1736a8b3dc0631e14b12fd81ba4136e8aaa99
commit 8d3d04ef588b54943bdc371de39c86d34947d3ff
Author: Julien Nabet <serval2412 at yahoo.fr>
Date:   Fri Jan 26 17:38:06 2018 +0100

    Modernize a bit connectivity (part2)
    
    by using for range loops
    
    Change-Id: Ibbc4cdaa78c4c9d88487132a2761ac1040b1ecd8
    Reviewed-on: https://gerrit.libreoffice.org/48713
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Julien Nabet <serval2412 at yahoo.fr>

diff --git a/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx
index 582f96428ffd..9f29b641e8cb 100644
--- a/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx
+++ b/connectivity/source/drivers/mork/MDatabaseMetaDataHelper.cxx
@@ -51,8 +51,9 @@ bool MDatabaseMetaDataHelper::getTableStrings( OConnection* _pCon,
     std::set<std::string> lists;
     MorkParser* pMork = _pCon->getMorkParser("AddressBook");
     pMork->retrieveLists(lists);
-    for (std::set<std::string>::const_iterator iter = lists.begin(); iter != lists.end(); ++iter) {
-        OUString groupTableName = OStringToOUString((*iter).c_str(), RTL_TEXTENCODING_UTF8);
+    for (auto const& elem : lists)
+    {
+        OUString groupTableName = OStringToOUString(elem.c_str(), RTL_TEXTENCODING_UTF8);
         SAL_INFO("connectivity.mork", "add Table " << groupTableName);
 
         _rStrings.push_back(groupTableName);
@@ -63,8 +64,9 @@ bool MDatabaseMetaDataHelper::getTableStrings( OConnection* _pCon,
     std::set<std::string> lists_history;
     pMork = _pCon->getMorkParser("CollectedAddressBook");
     pMork->retrieveLists(lists_history);
-    for (std::set<std::string>::const_iterator iter = lists_history.begin(); iter != lists_history.end(); ++iter) {
-        OUString groupTableName = OStringToOUString((*iter).c_str(), RTL_TEXTENCODING_UTF8);
+    for (auto const& elem : lists_history)
+    {
+        OUString groupTableName = OStringToOUString(elem.c_str(), RTL_TEXTENCODING_UTF8);
         SAL_INFO("connectivity.mork", "add Table " << groupTableName);
 
         _rStrings.push_back(groupTableName);
diff --git a/connectivity/source/drivers/mork/MPreparedStatement.cxx b/connectivity/source/drivers/mork/MPreparedStatement.cxx
index 716a87ca9c9e..81626de6b482 100644
--- a/connectivity/source/drivers/mork/MPreparedStatement.cxx

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list