summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2013-09-16 12:12:42 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2013-09-20 17:21:01 +0200
commitd2e4739c04acc237c707fdcfe72901e8ef24c6c8 (patch)
tree1f8d3a5d07f29fb4df939abba46a3eae41c982a3
parent25b01d8178e397ebb1d121c607582589fc3fd9b8 (diff)
bnc#825891 fdo#37606 SwWrtShell::SelAll(): fix for doc starting with table
SwWrtShell::SelAll() can now detect if the body text starts with a table, and if so, it explicitly selects the whole document, not just the first cell of the starting table. Also, SwCrsrShell::EndAction() now checks for this "select all and doc starts with table" situation, and if that's the case, it activates a special select all mode, so layout can act accordingly. (cherry picked from commit 3b11e66ab89c201591d8be8f1ab1af1aba11a821) Conflicts: sw/source/core/crsr/crsrsh.cxx sw/source/core/layout/trvlfrm.cxx fdo#37606 SwWrtShell: fix select all when doc starts with table and cursor ... ... is outside that table (cherry picked from commit 4b6445dba6bb5b2aed3edb4878ecb327446286e9) fdo#37606 SwEditShell::DeleteSel(): handle document starting with a table If the whole document is selected and the document starts with a table, then we used to delete the contents of the document, except the starting table, which was just cleared. Change this and do what is expected: remove the table as well, so the document will have a single empty paragraph only. (cherry picked from commit 0fb4adcff534e3841cf6df0e2363fb0797af7022) Conflicts: sw/source/core/edit/eddel.cxx fdo#37606 SwEditShell: fix copying when doc starts with a table ... ... and the whole document was selected The problem is that the cursor starts at the first cell of the starting table, but when copying, we want to copy the preceding startnode and tablenode as well. (cherry picked from commit 49505336a629a75f4fb48bbe0c532b402e857ed4) fdo#37606 testcase (cherry picked from commit f5fa78d75abac3dbe0f9edf9e9106f63ca5dca53) Conflicts: sw/qa/extras/odfimport/odfimport.cxx Change-Id: I60d34906a90a5143163e516f618648cf7178430e Conflicts: sw/CppunitTest_sw_odfimport.mk sw/inc/viewsh.hxx sw/qa/extras/odfimport/odfimport.cxx sw/source/core/crsr/crsrsh.cxx sw/source/core/view/vnew.cxx
-rw-r--r--sw/CppunitTest_sw_subsequent_odfimport.mk5
-rw-r--r--sw/inc/crsrsh.hxx4
-rw-r--r--sw/inc/viewsh.hxx2
-rw-r--r--sw/qa/extras/odfimport/data/fdo37606.odtbin0 -> 11389 bytes
-rw-r--r--sw/qa/extras/odfimport/odfimport.cxx74
-rw-r--r--sw/source/core/crsr/crsrsh.cxx31
-rw-r--r--sw/source/core/edit/eddel.cxx4
-rw-r--r--sw/source/core/edit/edglss.cxx12
-rw-r--r--sw/source/core/layout/trvlfrm.cxx5
-rw-r--r--sw/source/core/view/vnew.cxx2
-rw-r--r--sw/source/ui/inc/swdtflvr.hxx2
-rw-r--r--sw/source/ui/wrtsh/select.cxx9
12 files changed, 144 insertions, 6 deletions
diff --git a/sw/CppunitTest_sw_subsequent_odfimport.mk b/sw/CppunitTest_sw_subsequent_odfimport.mk
index f7ad4eb8dadf..23b5a8fe1657 100644
--- a/sw/CppunitTest_sw_subsequent_odfimport.mk
+++ b/sw/CppunitTest_sw_subsequent_odfimport.mk
@@ -38,6 +38,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_subsequent_odfimport, \
cppu \
cppuhelper \
sal \
+ svt \
sw \
test \
unotest \
@@ -53,6 +54,7 @@ $(eval $(call gb_CppunitTest_use_externals,sw_subsequent_odfimport,\
$(eval $(call gb_CppunitTest_set_include,sw_subsequent_odfimport,\
-I$(SRCDIR)/sw/inc \
-I$(SRCDIR)/sw/source/core/inc \
+ -I$(SRCDIR)/sw/source/ui/inc \
-I$(SRCDIR)/sw/qa/extras/inc \
$$(INCLUDE) \
))
@@ -87,6 +89,9 @@ $(eval $(call gb_CppunitTest_use_components,sw_subsequent_odfimport,\
unotools/util/utl \
unoxml/source/service/unoxml \
uui/util/uui \
+ $(if $(filter-out MACOSX WNT,$(OS)), \
+ vcl/vcl.unx \
+ ) \
$(if $(filter DESKTOP,$(BUILD_TYPE)),xmlhelp/util/ucpchelp1) \
))
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 5a061dbfa466..f8dfdd221f26 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -324,6 +324,10 @@ public:
// if ExtendedSelect() is called afterwards, the whole nodes array is selected
// only for usage in special cases allowed!
void ExtendedSelectAll();
+ /// If ExtendedSelectAll() was called and selection didn't change since then.
+ bool ExtendedSelectedAll();
+ /// If document body starts with a table.
+ bool StartsWithTable();
SwPaM* GetCrsr( sal_Bool bMakeTblCrsr = sal_True ) const;
inline SwCursor* GetSwCrsr( sal_Bool bMakeTblCrsr = sal_True ) const;
diff --git a/sw/inc/viewsh.hxx b/sw/inc/viewsh.hxx
index 3ddfbe410fc1..749023f4fa60 100644
--- a/sw/inc/viewsh.hxx
+++ b/sw/inc/viewsh.hxx
@@ -193,6 +193,7 @@ protected:
sal_uInt16 nStartAction; // != 0 if at least one ::com::sun::star::chaos::Action is active.
sal_uInt16 nLockPaint; // != 0 if Paint is locked.
+ bool mbSelectAll; ///< Special select all mode: whole document selected, even if doc starts with table.
public:
TYPEINFO();
@@ -564,6 +565,7 @@ public:
bool IsHeaderFooterEdit() const { return bHeaderFooterEdit; }
bool IsShowHeaderFooterSeparator( FrameControlType eControl ) { return (eControl == Header)? bShowHeaderSeparator: bShowFooterSeparator; }
virtual void SetShowHeaderFooterSeparator( FrameControlType eControl, bool bShow ) { if ( eControl == Header ) bShowHeaderSeparator = bShow; else bShowFooterSeparator = bShow; }
+ bool IsSelectAll() { return mbSelectAll; }
};
//---- class CurrShell manages global ShellPointer -------------------
diff --git a/sw/qa/extras/odfimport/data/fdo37606.odt b/sw/qa/extras/odfimport/data/fdo37606.odt
new file mode 100644
index 000000000000..462984f11303
--- /dev/null
+++ b/sw/qa/extras/odfimport/data/fdo37606.odt
Binary files differ
diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx
index 8d86bd553771..456eb503ac54 100644
--- a/sw/qa/extras/odfimport/odfimport.cxx
+++ b/sw/qa/extras/odfimport/odfimport.cxx
@@ -30,6 +30,12 @@
#include <com/sun/star/text/XTextTable.hpp>
#include <swmodeltestbase.hxx>
+#include <wrtsh.hxx>
+#include <ndtxt.hxx>
+#include <swdtflvr.hxx>
+#include <view.hxx>
+#include <edtwin.hxx>
+
typedef std::map<OUString, com::sun::star::uno::Sequence< com::sun::star::table::BorderLine> > AllBordersMap;
typedef std::pair<OUString, com::sun::star::uno::Sequence< com::sun::star::table::BorderLine> > StringSequencePair;
@@ -40,6 +46,8 @@ public:
void testHideAllSections();
void testOdtBorders();
void testFdo56272();
+ void testFdo37606();
+ void testFdo37606Copy();
CPPUNIT_TEST_SUITE(Test);
#if !defined(MACOSX) && !defined(WNT)
@@ -58,9 +66,13 @@ void Test::run()
{"fdo53210.odt", &Test::testHideAllSections},
{"borders_ooo33.odt", &Test::testOdtBorders},
{"fdo56272.odt", &Test::testFdo56272},
+ {"fdo37606.odt", &Test::testFdo37606},
+ {"fdo37606.odt", &Test::testFdo37606Copy},
};
for (unsigned int i = 0; i < SAL_N_ELEMENTS(aMethods); ++i)
{
+ if (mxComponent.is())
+ mxComponent->dispose();
MethodEntry<Test>& rEntry = aMethods[i];
mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/odfimport/data/") + OUString::createFromAscii(rEntry.pName));
(this->*rEntry.pMethod)();
@@ -281,6 +293,68 @@ void Test::testFdo56272()
CPPUNIT_ASSERT_EQUAL(sal_Int32(422), xShape->getPosition().Y); // Was -2371
}
+void Test::testFdo37606()
+{
+ SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ SwWrtShell* pWrtShell = pTxtDoc->GetDocShell()->GetWrtShell();
+ SwShellCrsr* pShellCrsr = pWrtShell->getShellCrsr(false);
+
+ {
+ pWrtShell->SelAll();
+ SwTxtNode& rStart = dynamic_cast<SwTxtNode&>(pShellCrsr->Start()->nNode.GetNode());
+ CPPUNIT_ASSERT_EQUAL(String("A1"), rStart.GetTxt());
+
+ SwTxtNode& rEnd = dynamic_cast<SwTxtNode&>(pShellCrsr->End()->nNode.GetNode());
+ // This was "A1", i.e. Ctrl-A only selected the A1 cell of the table, not the whole document.
+ CPPUNIT_ASSERT_EQUAL(String("Hello."), rEnd.GetTxt());
+ }
+
+ {
+ pWrtShell->SttEndDoc(false); // Go to the end of the doc.
+ pWrtShell->SelAll(); // And now that we're outside of the table, try Ctrl-A again.
+ SwTxtNode& rStart = dynamic_cast<SwTxtNode&>(pShellCrsr->Start()->nNode.GetNode());
+ // This was "Hello", i.e. Ctrl-A did not select the starting table.
+ CPPUNIT_ASSERT_EQUAL(String("A1"), rStart.GetTxt());
+
+ SwTxtNode& rEnd = dynamic_cast<SwTxtNode&>(pShellCrsr->End()->nNode.GetNode());
+ CPPUNIT_ASSERT_EQUAL(String("Hello."), rEnd.GetTxt());
+ }
+
+ {
+ pWrtShell->Delete(); // Delete the selection
+ // And make sure the table got deleted as well.
+ SwNodes& rNodes = pWrtShell->GetDoc()->GetNodes();
+ SwNodeIndex nNode(rNodes.GetEndOfExtras());
+ SwCntntNode* pCntntNode = rNodes.GoNext(&nNode);
+ // First content node was in a table -> table wasn't deleted.
+ CPPUNIT_ASSERT(!pCntntNode->FindTableNode());
+ }
+}
+
+void Test::testFdo37606Copy()
+{
+ SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ SwWrtShell* pWrtShell = pTxtDoc->GetDocShell()->GetWrtShell();
+ // Ctrl-A
+ pWrtShell->SelAll();
+
+ // Ctrl-C
+ SwTransferable* pTransferable = new SwTransferable(*pWrtShell);
+ uno::Reference<datatransfer::XTransferable> xTransferable(pTransferable);
+ pTransferable->Copy();
+
+ pWrtShell->SttEndDoc(false); // Go to the end of the doc.
+
+ // Ctrl-V
+ TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromSystemClipboard(&pWrtShell->GetView().GetEditWin()));
+ SwTransferable::Paste( *pWrtShell, aDataHelper );
+
+ // Previously copy&paste failed to copy the table in case it was the document-starting one.
+ uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index ac00ff73114b..75dec387d2c0 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -58,6 +58,7 @@
#include <numrule.hxx>
#include <IGrammarContact.hxx>
+#include <comphelper/flagguard.hxx>
#include <globals.hrc>
#include <comcore.hrc>
@@ -238,6 +239,7 @@ void SwCrsrShell::StartAction()
void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
{
sal_Bool bVis = bSVCrsrVis;
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll());
// Idle-formatting?
if( bIdleEnd && Imp()->GetRegion() )
@@ -545,6 +547,32 @@ void SwCrsrShell::ExtendedSelectAll()
pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
}
+bool SwCrsrShell::ExtendedSelectedAll()
+{
+ SwNodes& rNodes = GetDoc()->GetNodes();
+ SwNodeIndex nNode = rNodes.GetEndOfPostIts();
+ SwCntntNode* pStart = rNodes.GoNext(&nNode);
+
+ nNode = rNodes.GetEndOfContent();
+ SwCntntNode* pEnd = rNodes.GoPrevious(&nNode);
+
+ if (!pStart || !pEnd)
+ return false;
+
+ SwPosition aStart(*pStart, 0);
+ SwPosition aEnd(*pEnd, pEnd->Len());
+ SwShellCrsr* pShellCrsr = getShellCrsr(false);
+ return aStart == *pShellCrsr->Start() && aEnd == *pShellCrsr->End();
+}
+
+bool SwCrsrShell::StartsWithTable()
+{
+ SwNodes& rNodes = GetDoc()->GetNodes();
+ SwNodeIndex nNode(rNodes.GetEndOfExtras());
+ SwCntntNode* pCntntNode = rNodes.GoNext(&nNode);
+ return pCntntNode->FindTableNode();
+}
+
sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
{
sal_Bool bRet = sal_False;
@@ -1130,6 +1158,7 @@ sal_Bool SwCrsrShell::GoPrevCrsr()
void SwCrsrShell::Paint( const Rectangle &rRect)
{
+ comphelper::FlagRestorationGuard g(mbSelectAll, StartsWithTable() && ExtendedSelectedAll());
SET_CURR_SHELL( this );
// always switch off all cursors when painting
@@ -1311,7 +1340,7 @@ void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
( pTblCrsr ||
pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
- pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
+ pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) && !mbSelectAll)
{
SwShellCrsr* pITmpCrsr = getShellCrsr( true );
Point aTmpPt( pITmpCrsr->GetPtPos() );
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index ca20b2d2d997..1f98618f3507 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -39,6 +39,7 @@
void SwEditShell::DeleteSel( SwPaM& rPam, sal_Bool* pUndo )
{
+ bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
// nur bei Selektion
if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
return;
@@ -49,9 +50,10 @@ void SwEditShell::DeleteSel( SwPaM& rPam, sal_Bool* pUndo )
// 1. Point und Mark stehen in einer Box, Selection normal loeschen
// 2. Point und Mark stehen in unterschiedlichen Boxen, alle
// selektierten Boxen suchen in den Inhalt loeschen
+ // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
if( rPam.GetNode()->FindTableNode() &&
rPam.GetNode()->StartOfSectionNode() !=
- rPam.GetNode(sal_False)->StartOfSectionNode() )
+ rPam.GetNode(sal_False)->StartOfSectionNode() && !bSelectAll )
{
// in Tabellen das Undo gruppieren
if( pUndo && !*pUndo )
diff --git a/sw/source/core/edit/edglss.cxx b/sw/source/core/edit/edglss.cxx
index 9125987b92b6..8828b97e6249 100644
--- a/sw/source/core/edit/edglss.cxx
+++ b/sw/source/core/edit/edglss.cxx
@@ -226,6 +226,7 @@ sal_Bool SwEditShell::_CopySelToDoc( SwDoc* pInsDoc, SwNodeIndex* pSttNd )
bool bColSel = _GetCrsr()->IsColumnSelection();
if( bColSel && pInsDoc->IsClipBoard() )
pInsDoc->SetColumnSelection( true );
+ bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
{
FOREACHPAM_START(this)
@@ -244,7 +245,16 @@ sal_Bool SwEditShell::_CopySelToDoc( SwDoc* pInsDoc, SwNodeIndex* pSttNd )
}
else
{
- bRet = GetDoc()->CopyRange( *PCURCRSR, aPos, false ) || bRet;
+ // Make a copy, so that in case we need to adjust the selection
+ // for the purpose of copying, our shell cursor is not touched.
+ // (Otherwise we would have to restore it.)
+ SwPaM aPaM(*PCURCRSR);
+ if (bSelectAll)
+ // Selection starts at the first para of the first cell,
+ // but we want to copy the table and the start node before
+ // the first cell as well.
+ aPaM.Start()->nNode = aPaM.Start()->nNode.GetNode().FindTableNode()->GetIndex();
+ bRet = GetDoc()->CopyRange( aPaM, aPos, false ) || bRet;
}
FOREACHPAM_END()
diff --git a/sw/source/core/layout/trvlfrm.cxx b/sw/source/core/layout/trvlfrm.cxx
index 6e60864d4364..538ea61280ed 100644
--- a/sw/source/core/layout/trvlfrm.cxx
+++ b/sw/source/core/layout/trvlfrm.cxx
@@ -2581,6 +2581,9 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode )
bool const bBody = pStartFrm->IsInDocBody();
const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
+ if (pSh->IsSelectAll())
+ pCellBox = 0;
+
const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
SwRect aPrvRect;
@@ -2602,6 +2605,8 @@ void SwRootFrm::CalcFrmRects( SwShellCrsr &rCrsr, sal_Bool bIsTblMode )
// same cell frame (or its follow cell)
const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
+ if (pSh->IsSelectAll())
+ pTmpCellBox = 0;
if ( bBody == pCntnt->IsInDocBody() &&
( !pCellBox || pCellBox == pTmpCellBox ) )
{
diff --git a/sw/source/core/view/vnew.cxx b/sw/source/core/view/vnew.cxx
index 56b48828aefd..1fb847897971 100644
--- a/sw/source/core/view/vnew.cxx
+++ b/sw/source/core/view/vnew.cxx
@@ -196,6 +196,7 @@ ViewShell::ViewShell( SwDoc& rDocument, Window *pWindow,
pDoc( &rDocument ),
nStartAction( 0 ),
nLockPaint( 0 ),
+ mbSelectAll(false),
mpPrePostOutDev(0), // #i72754#
maPrePostMapMode()
{
@@ -279,6 +280,7 @@ ViewShell::ViewShell( ViewShell& rShell, Window *pWindow,
pDoc( rShell.GetDoc() ),
nStartAction( 0 ),
nLockPaint( 0 ),
+ mbSelectAll(false),
mpPrePostOutDev(0), // #i72754#
maPrePostMapMode()
{
diff --git a/sw/source/ui/inc/swdtflvr.hxx b/sw/source/ui/inc/swdtflvr.hxx
index 9a87ec66092a..8466691f09bb 100644
--- a/sw/source/ui/inc/swdtflvr.hxx
+++ b/sw/source/ui/inc/swdtflvr.hxx
@@ -54,7 +54,7 @@ namespace nsTransferBufferType
#define DATA_FLAVOR ::com::sun::star::datatransfer::DataFlavor
-class SwTransferable : public TransferableHelper
+class SW_DLLPUBLIC SwTransferable : public TransferableHelper
{
friend class SwView_Impl;
SfxObjectShellLock aDocShellRef;
diff --git a/sw/source/ui/wrtsh/select.cxx b/sw/source/ui/wrtsh/select.cxx
index d089a8ccd833..c57c13c9e952 100644
--- a/sw/source/ui/wrtsh/select.cxx
+++ b/sw/source/ui/wrtsh/select.cxx
@@ -159,6 +159,11 @@ long SwWrtShell::SelAll()
}
SttSelect();
GoEnd(sal_True, &bMoveTable);
+
+ bool bStartsWithTable = StartsWithTable();
+ if (bStartsWithTable)
+ ExtendedSelectAll();
+
if( pStartPos )
{
pTmpCrsr = getShellCrsr( false );
@@ -169,9 +174,9 @@ long SwWrtShell::SelAll()
// if the last selection was behind the first section or
// if the last selection was already the first section
// In this both cases we select to the end of document
- if( *pTmpCrsr->GetPoint() < *pEndPos ||
+ if( ( *pTmpCrsr->GetPoint() < *pEndPos ||
( *pStartPos == *pTmpCrsr->GetMark() &&
- *pEndPos == *pTmpCrsr->GetPoint() ) )
+ *pEndPos == *pTmpCrsr->GetPoint() ) ) && !bStartsWithTable)
SwCrsrShell::SttEndDoc(sal_False);
}
delete pStartPos;