1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <sal/config.h>
21
22 #include <o3tl/safeint.hxx>
23 #include <osl/diagnose.h>
24 #include <osl/endian.h>
25 #include <tools/urlobj.hxx>
26 #include <doc.hxx>
27 #include <IDocumentRedlineAccess.hxx>
28 #include <IDocumentFieldsAccess.hxx>
29 #include <pam.hxx>
30 #include <editsh.hxx>
31 #include <frmfmt.hxx>
32 #include <rootfrm.hxx>
33 #include <ndtxt.hxx>
34 #include <swtable.hxx>
35 #include <shellio.hxx>
36 #include <iodetect.hxx>
37 #include <frameformats.hxx>
38
InsertGlossary(SwTextBlocks & rGlossary,const OUString & rStr)39 void SwEditShell::InsertGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
40 {
41 StartAllAction();
42 GetDoc()->InsertGlossary( rGlossary, rStr, *GetCursor(), this );
43 EndAllAction();
44 }
45
46 /// convert current selection into text block and add to the text block document, incl. templates
MakeGlossary(SwTextBlocks & rBlks,const OUString & rName,const OUString & rShortName,bool bSaveRelFile,const OUString * pOnlyText)47 sal_uInt16 SwEditShell::MakeGlossary( SwTextBlocks& rBlks, const OUString& rName, const OUString& rShortName,
48 bool bSaveRelFile, const OUString* pOnlyText )
49 {
50 SwDoc* pGDoc = rBlks.GetDoc();
51
52 OUString sBase;
53 if(bSaveRelFile)
54 {
55 INetURLObject aURL( rBlks.GetFileName() );
56 sBase = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
57 }
58 rBlks.SetBaseURL( sBase );
59
60 if( pOnlyText )
61 return rBlks.PutText( rShortName, rName, *pOnlyText );
62
63 rBlks.ClearDoc();
64 if( rBlks.BeginPutDoc( rShortName, rName ) )
65 {
66 rBlks.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
67 CopySelToDoc(*pGDoc);
68 rBlks.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );
69 return rBlks.PutDoc();
70 }
71
72 return USHRT_MAX;
73 }
74
SaveGlossaryDoc(SwTextBlocks & rBlock,const OUString & rName,const OUString & rShortName,bool bSaveRelFile,bool bOnlyText)75 sal_uInt16 SwEditShell::SaveGlossaryDoc( SwTextBlocks& rBlock,
76 const OUString& rName,
77 const OUString& rShortName,
78 bool bSaveRelFile,
79 bool bOnlyText )
80 {
81 StartAllAction();
82
83 SwDoc* pGDoc = rBlock.GetDoc();
84 SwDoc* pMyDoc = GetDoc();
85
86 OUString sBase;
87 if(bSaveRelFile)
88 {
89 INetURLObject aURL( rBlock.GetFileName() );
90 sBase = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
91 }
92 rBlock.SetBaseURL( sBase );
93 sal_uInt16 nRet = USHRT_MAX;
94
95 if( bOnlyText )
96 {
97 KillPams();
98
99 SwPaM* pCursor = GetCursor();
100
101 SwNodeIndex aStt( pMyDoc->GetNodes().GetEndOfExtras(), 1 );
102 SwContentNode* pContentNd = pMyDoc->GetNodes().GoNext( &aStt );
103 const SwNode* pNd = pContentNd->FindTableNode();
104 if( !pNd )
105 pNd = pContentNd;
106
107 pCursor->GetPoint()->nNode = *pNd;
108 if( pNd == pContentNd )
109 pCursor->GetPoint()->nContent.Assign( pContentNd, 0 );
110 pCursor->SetMark();
111
112 // then until the end of the Node array
113 pCursor->GetPoint()->nNode = pMyDoc->GetNodes().GetEndOfContent().GetIndex()-1;
114 pContentNd = pCursor->GetContentNode();
115 if( pContentNd )
116 pCursor->GetPoint()->nContent.Assign( pContentNd, pContentNd->Len() );
117
118 OUString sBuf;
119 GetSelectedText( sBuf, ParaBreakType::ToOnlyCR );
120 if( !sBuf.isEmpty() )
121 nRet = rBlock.PutText( rShortName, rName, sBuf );
122 }
123 else
124 {
125 rBlock.ClearDoc();
126 if( rBlock.BeginPutDoc( rShortName, rName ) )
127 {
128 SwNodeIndex aStt( pMyDoc->GetNodes().GetEndOfExtras(), 1 );
129 SwContentNode* pContentNd = pMyDoc->GetNodes().GoNext( &aStt );
130 const SwNode* pNd = pContentNd->FindTableNode();
131 if( !pNd ) pNd = pContentNd;
132 SwPaM aCpyPam( *pNd );
133 aCpyPam.SetMark();
134
135 // then until the end of the nodes array
136 aCpyPam.GetPoint()->nNode = pMyDoc->GetNodes().GetEndOfContent().GetIndex()-1;
137 pContentNd = aCpyPam.GetContentNode();
138 aCpyPam.GetPoint()->nContent.Assign(
139 pContentNd, pContentNd ? pContentNd->Len() : 0);
140
141 aStt = pGDoc->GetNodes().GetEndOfExtras();
142 pContentNd = pGDoc->GetNodes().GoNext( &aStt );
143 SwPosition aInsPos( aStt, SwIndex( pContentNd ));
144 pMyDoc->getIDocumentContentOperations().CopyRange(aCpyPam, aInsPos, SwCopyFlags::CheckPosInFly);
145
146 nRet = rBlock.PutDoc();
147 }
148 }
149 EndAllAction();
150 return nRet;
151 }
152
153 /// copy all selections to the doc
CopySelToDoc(SwDoc & rInsDoc)154 bool SwEditShell::CopySelToDoc( SwDoc& rInsDoc )
155 {
156 SwNodes& rNds = rInsDoc.GetNodes();
157
158 SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
159 SwContentNode *const pContentNode = aIdx.GetNode().GetContentNode();
160 SwPosition aPos( aIdx,
161 SwIndex(pContentNode, pContentNode ? pContentNode->Len() : 0));
162
163 bool bRet = false;
164 CurrShell aCurr( this );
165
166 rInsDoc.getIDocumentFieldsAccess().LockExpFields();
167
168 if( IsTableMode() )
169 {
170 // Copy parts of a table: create a table with the width of the original one and copy the
171 // selected boxes. The sizes are corrected on a percentage basis.
172
173 // search boxes using the layout
174 SwTableNode* pTableNd;
175 SwSelBoxes aBoxes;
176 GetTableSel( *this, aBoxes );
177 if( !aBoxes.empty() && nullptr != (pTableNd = const_cast<SwTableNode*>(aBoxes[0]
178 ->GetSttNd()->FindTableNode()) ))
179 {
180 // check if the table name can be copied
181 bool bCpyTableNm = aBoxes.size() == pTableNd->GetTable().GetTabSortBoxes().size();
182 if( bCpyTableNm )
183 {
184 const OUString rTableName = pTableNd->GetTable().GetFrameFormat()->GetName();
185 const SwFrameFormats& rTableFormats = *rInsDoc.GetTableFrameFormats();
186 for( auto n = rTableFormats.size(); n; )
187 if( rTableFormats[ --n ]->GetName() == rTableName )
188 {
189 bCpyTableNm = false;
190 break;
191 }
192 }
193 bRet = rInsDoc.InsCopyOfTable( aPos, aBoxes, nullptr, bCpyTableNm, false, pTableNd->GetTable().GetTableStyleName() );
194 }
195 else
196 bRet = false;
197 }
198 else
199 {
200 bool bColSel = GetCursor_()->IsColumnSelection();
201 if( bColSel && rInsDoc.IsClipBoard() )
202 rInsDoc.SetColumnSelection( true );
203 bool bSelectAll = StartsWithTable() && ExtendedSelectedAll();
204 {
205 for(SwPaM& rPaM : GetCursor()->GetRingContainer())
206 {
207 if( !rPaM.HasMark() )
208 {
209 SwContentNode *const pNd = rPaM.GetContentNode();
210 if (nullptr != pNd &&
211 ( bColSel || !pNd->GetTextNode() ) )
212 {
213 rPaM.SetMark();
214 rPaM.Move( fnMoveForward, GoInContent );
215 bRet = GetDoc()->getIDocumentContentOperations().CopyRange(rPaM, aPos, SwCopyFlags::CheckPosInFly)
216 || bRet;
217 rPaM.Exchange();
218 rPaM.DeleteMark();
219 }
220 }
221 else
222 {
223 // Make a copy, so that in case we need to adjust the selection
224 // for the purpose of copying, our shell cursor is not touched.
225 // (Otherwise we would have to restore it.)
226 SwPaM aPaM(*rPaM.GetMark(), *rPaM.GetPoint());
227 if (bSelectAll)
228 {
229 // Selection starts at the first para of the first cell,
230 // but we want to copy the table and the start node before
231 // the first cell as well.
232 // tdf#133982 tables can be nested
233 while (SwTableNode const* pTableNode =
234 aPaM.Start()->nNode.GetNode().StartOfSectionNode()->FindTableNode())
235 {
236 aPaM.Start()->nNode = *pTableNode;
237 }
238 while (SwSectionNode const* pSectionNode =
239 aPaM.Start()->nNode.GetNode().StartOfSectionNode()->FindSectionNode())
240 {
241 aPaM.Start()->nNode = *pSectionNode;
242 }
243 aPaM.Start()->nContent.Assign(nullptr, 0);
244 }
245 bRet = GetDoc()->getIDocumentContentOperations().CopyRange( aPaM, aPos, SwCopyFlags::CheckPosInFly)
246 || bRet;
247 }
248 }
249 }
250 }
251
252 rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
253 if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
254 rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
255
256 return bRet;
257 }
258
259 /** Get text in a Selection
260 */
GetSelectedText(OUString & rBuf,ParaBreakType nHndlParaBrk)261 void SwEditShell::GetSelectedText( OUString &rBuf, ParaBreakType nHndlParaBrk )
262 {
263 GetCursor(); // creates all cursors if needed
264 if( IsSelOnePara() )
265 {
266 rBuf = GetSelText();
267 if( ParaBreakType::ToBlank == nHndlParaBrk )
268 {
269 rBuf = rBuf.replaceAll("\x0a", " ");
270 }
271 else if( IsSelFullPara() &&
272 ParaBreakType::ToOnlyCR != nHndlParaBrk )
273 {
274 #ifdef _WIN32
275 rBuf += "\015\012";
276 #else
277 rBuf += "\012";
278 #endif
279 }
280 }
281 else if( IsSelection() )
282 {
283 SvMemoryStream aStream;
284 #ifdef OSL_BIGENDIAN
285 aStream.SetEndian( SvStreamEndian::BIG );
286 #else
287 aStream.SetEndian( SvStreamEndian::LITTLE );
288 #endif
289 WriterRef xWrt;
290 SwReaderWriter::GetWriter( FILTER_TEXT, OUString(), xWrt );
291 if( xWrt.is() )
292 {
293 // write selected areas into an ASCII document
294 SwWriter aWriter( aStream, *this);
295 xWrt->SetShowProgress(false);
296
297 switch( nHndlParaBrk )
298 {
299 case ParaBreakType::ToBlank:
300 xWrt->m_bASCII_ParaAsBlank = true;
301 xWrt->m_bASCII_NoLastLineEnd = true;
302 break;
303
304 case ParaBreakType::ToOnlyCR:
305 xWrt->m_bASCII_ParaAsCR = true;
306 xWrt->m_bASCII_NoLastLineEnd = true;
307 break;
308 }
309
310 //JP 09.05.00: write as UNICODE ! (and not as ANSI)
311 SwAsciiOptions aAsciiOpt( xWrt->GetAsciiOptions() );
312 aAsciiOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
313 xWrt->SetAsciiOptions( aAsciiOpt );
314 xWrt->m_bUCS2_WithStartChar = false;
315 xWrt->m_bHideDeleteRedlines = GetLayout()->IsHideRedlines();
316
317 if ( ! aWriter.Write(xWrt).IsError() )
318 {
319 aStream.WriteUInt16( '\0' );
320
321 const sal_Unicode *p = static_cast<sal_Unicode const *>(aStream.GetData());
322 if (p)
323 rBuf = OUString(p);
324 else
325 {
326 const sal_uInt64 nLen = aStream.GetSize();
327 OSL_ENSURE( nLen/sizeof( sal_Unicode )<o3tl::make_unsigned(SAL_MAX_INT32), "Stream can't fit in OUString" );
328 rtl_uString *pStr = rtl_uString_alloc(static_cast<sal_Int32>(nLen / sizeof( sal_Unicode )));
329 aStream.Seek( 0 );
330 aStream.ResetError();
331 //endian specific?, yipes!
332 aStream.ReadBytes(pStr->buffer, nLen);
333 rBuf = OUString(pStr, SAL_NO_ACQUIRE);
334 }
335 }
336 }
337 }
338 }
339
340 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
341