Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <vcl/wrkwin.hxx>
31 : : #include <vcl/dialog.hxx>
32 : : #include <vcl/msgbox.hxx>
33 : : #include <vcl/svapp.hxx>
34 : :
35 : : #include <svl/srchitem.hxx>
36 : : #include <editeng/lspcitem.hxx>
37 : : #include <editeng/adjitem.hxx>
38 : : #include <editeng/tstpitem.hxx>
39 : :
40 : : #include <eertfpar.hxx>
41 : : #include <editeng/editeng.hxx>
42 : : #include <impedit.hxx>
43 : : #include <editeng/editview.hxx>
44 : : #include <eehtml.hxx>
45 : : #include <editobj2.hxx>
46 : : #include <i18npool/lang.h>
47 : :
48 : : #include "editxml.hxx"
49 : :
50 : : #include <editeng/akrnitem.hxx>
51 : : #include <editeng/cntritem.hxx>
52 : : #include <editeng/colritem.hxx>
53 : : #include <editeng/crsditem.hxx>
54 : : #include <editeng/escpitem.hxx>
55 : : #include <editeng/fhgtitem.hxx>
56 : : #include <editeng/fontitem.hxx>
57 : : #include <editeng/kernitem.hxx>
58 : : #include <editeng/lrspitem.hxx>
59 : : #include <editeng/postitem.hxx>
60 : : #include <editeng/shdditem.hxx>
61 : : #include <editeng/udlnitem.hxx>
62 : : #include <editeng/ulspitem.hxx>
63 : : #include <editeng/wghtitem.hxx>
64 : : #include <editeng/langitem.hxx>
65 : : #include <editeng/charreliefitem.hxx>
66 : : #include <editeng/frmdiritem.hxx>
67 : : #include <editeng/emphitem.hxx>
68 : : #include <textconv.hxx>
69 : : #include <rtl/tencinfo.h>
70 : : #include <svtools/rtfout.hxx>
71 : : #include <edtspell.hxx>
72 : : #include <editeng/scripttypeitem.hxx>
73 : : #include <editeng/unolingu.hxx>
74 : : #include <linguistic/lngprops.hxx>
75 : : #include <com/sun/star/linguistic2/XThesaurus.hpp>
76 : : #include <com/sun/star/linguistic2/XMeaning.hpp>
77 : : #include <com/sun/star/i18n/ScriptType.hpp>
78 : : #include <com/sun/star/i18n/WordType.hpp>
79 : : #include <com/sun/star/i18n/TransliterationModules.hpp>
80 : : #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
81 : : #include <unotools/transliterationwrapper.hxx>
82 : : #include <unotools/textsearch.hxx>
83 : : #include <comphelper/processfactory.hxx>
84 : : #include <vcl/help.hxx>
85 : : #include <svtools/rtfkeywd.hxx>
86 : : #include <editeng/edtdlg.hxx>
87 : :
88 : : #include <vector>
89 : :
90 : : using namespace ::com::sun::star;
91 : : using namespace ::com::sun::star::uno;
92 : : using namespace ::com::sun::star::beans;
93 : : using namespace ::com::sun::star::linguistic2;
94 : :
95 : 0 : void Swapsal_uIt16s( sal_uInt16& rX, sal_uInt16& rY )
96 : : {
97 : 0 : sal_uInt16 n = rX;
98 : 0 : rX = rY;
99 : 0 : rY = n;
100 : 0 : }
101 : :
102 : 3 : EditPaM ImpEditEngine::Read( SvStream& rInput, const String& rBaseURL, EETextFormat eFormat, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
103 : : {
104 : 3 : sal_Bool _bUpdate = GetUpdateMode();
105 : 3 : SetUpdateMode( sal_False );
106 : 3 : EditPaM aPaM;
107 [ - + ]: 3 : if ( eFormat == EE_FORMAT_TEXT )
108 [ # # ][ # # ]: 0 : aPaM = ReadText( rInput, aSel );
109 [ - + ]: 3 : else if ( eFormat == EE_FORMAT_RTF )
110 [ # # ][ # # ]: 0 : aPaM = ReadRTF( rInput, aSel );
111 [ - + ]: 3 : else if ( eFormat == EE_FORMAT_XML )
112 [ # # ][ # # ]: 0 : aPaM = ReadXML( rInput, aSel );
113 [ + - ]: 3 : else if ( eFormat == EE_FORMAT_HTML )
114 [ + - ][ + - ]: 3 : aPaM = ReadHTML( rInput, rBaseURL, aSel, pHTTPHeaderAttrs );
115 [ # # ]: 0 : else if ( eFormat == EE_FORMAT_BIN)
116 [ # # ][ # # ]: 0 : aPaM = ReadBin( rInput, aSel );
117 : : else
118 : : {
119 : : OSL_FAIL( "Read: Unknown Format" );
120 : : }
121 : :
122 : 3 : FormatFullDoc(); // perhaps a simple format is enough?
123 : 3 : SetUpdateMode( _bUpdate );
124 : :
125 : 3 : return aPaM;
126 : : }
127 : :
128 : 0 : EditPaM ImpEditEngine::ReadText( SvStream& rInput, EditSelection aSel )
129 : : {
130 [ # # ][ # # ]: 0 : if ( aSel.HasRange() )
131 [ # # ][ # # ]: 0 : aSel = ImpDeleteSelection( aSel );
132 [ # # ]: 0 : EditPaM aPaM = aSel.Max();
133 : :
134 [ # # ][ # # ]: 0 : XubString aTmpStr, aStr;
135 [ # # ]: 0 : sal_Bool bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() );
136 [ # # ]: 0 : while ( bDone )
137 : : {
138 [ # # ]: 0 : aTmpStr.Erase( MAXCHARSINPARA );
139 [ # # ][ # # ]: 0 : aPaM = ImpInsertText( EditSelection( aPaM, aPaM ), aTmpStr );
[ # # ]
140 [ # # ][ # # ]: 0 : aPaM = ImpInsertParaBreak( aPaM );
141 [ # # ]: 0 : bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() );
142 : : }
143 [ # # ][ # # ]: 0 : return aPaM;
144 : : }
145 : :
146 : 0 : EditPaM ImpEditEngine::ReadXML( SvStream& rInput, EditSelection aSel )
147 : : {
148 [ # # ][ # # ]: 0 : if ( aSel.HasRange() )
149 [ # # ][ # # ]: 0 : aSel = ImpDeleteSelection( aSel );
150 : :
151 [ # # ]: 0 : ESelection aESel = CreateESel( aSel );
152 : :
153 [ # # ]: 0 : ::SvxReadXML( *GetEditEnginePtr(), rInput, aESel );
154 : :
155 [ # # ]: 0 : return aSel.Max();
156 : : }
157 : :
158 : 0 : EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel )
159 : : {
160 : : #if (OSL_DEBUG_LEVEL > 2) && !defined( UNX )
161 : : SvFileStream aRTFOut( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_in.rtf" ) ), STREAM_WRITE );
162 : : aRTFOut << rInput;
163 : : aRTFOut.Close();
164 : : rInput.Seek( 0 );
165 : : #endif
166 [ # # ][ # # ]: 0 : if ( aSel.HasRange() )
167 [ # # ][ # # ]: 0 : aSel = ImpDeleteSelection( aSel );
168 : :
169 : : // The SvRTF parser expects the Which-mapping passed on in the pool, not
170 : : // dependant on a secondary.
171 : 0 : SfxItemPool* pPool = &aEditDoc.GetItemPool();
172 [ # # ][ # # ]: 0 : while (pPool->GetSecondaryPool() && !pPool->GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EditEngineItemPool")))
[ # # ][ # # ]
[ # # ]
173 : : {
174 [ # # ]: 0 : pPool = pPool->GetSecondaryPool();
175 : :
176 : : }
177 : :
178 : : DBG_ASSERT(pPool && pPool->GetName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EditEngineItemPool")),
179 : : "ReadRTF: no EditEnginePool!");
180 : :
181 [ # # ][ # # ]: 0 : EditRTFParserRef xPrsr = new EditRTFParser(rInput, aSel, *pPool, pEditEngine);
[ # # ]
182 [ # # ]: 0 : SvParserState eState = xPrsr->CallParser();
183 [ # # ][ # # ]: 0 : if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
[ # # ]
184 : : {
185 [ # # ]: 0 : rInput.SetError( EE_READWRITE_WRONGFORMAT );
186 [ # # ]: 0 : return aSel.Min();
187 : : }
188 [ # # ][ # # ]: 0 : return xPrsr->GetCurPaM();
189 : : }
190 : :
191 : 3 : EditPaM ImpEditEngine::ReadHTML( SvStream& rInput, const String& rBaseURL, EditSelection aSel, SvKeyValueIterator* pHTTPHeaderAttrs )
192 : : {
193 [ + - ][ - + ]: 3 : if ( aSel.HasRange() )
194 [ # # ][ # # ]: 0 : aSel = ImpDeleteSelection( aSel );
195 : :
196 [ + - ][ + - ]: 3 : EditHTMLParserRef xPrsr = new EditHTMLParser( rInput, rBaseURL, pHTTPHeaderAttrs );
197 [ + - ]: 3 : SvParserState eState = xPrsr->CallParser(pEditEngine, aSel.Max());
198 [ - + ][ # # ]: 3 : if ( ( eState != SVPAR_ACCEPTED ) && ( !rInput.GetError() ) )
[ - + ]
199 : : {
200 [ # # ]: 0 : rInput.SetError( EE_READWRITE_WRONGFORMAT );
201 [ # # ]: 0 : return aSel.Min();
202 : : }
203 [ + - ][ + - ]: 3 : return xPrsr->GetCurSelection().Max();
204 : : }
205 : :
206 : 0 : EditPaM ImpEditEngine::ReadBin( SvStream& rInput, EditSelection aSel )
207 : : {
208 : : // Simply abuse a temporary text object ...
209 : 0 : EditTextObject* pObj = EditTextObject::Create( rInput, NULL );
210 : :
211 : 0 : EditPaM aLastPaM = aSel.Max();
212 [ # # ]: 0 : if ( pObj )
213 [ # # ][ # # ]: 0 : aLastPaM = InsertText( *pObj, aSel ).Max();
214 : :
215 [ # # ]: 0 : delete pObj;
216 : 0 : return aLastPaM;
217 : : }
218 : :
219 : 0 : void ImpEditEngine::Write( SvStream& rOutput, EETextFormat eFormat, EditSelection aSel )
220 : : {
221 [ # # ]: 0 : if ( !rOutput.IsWritable() )
222 : 0 : rOutput.SetError( SVSTREAM_WRITE_ERROR );
223 : :
224 [ # # ]: 0 : if ( !rOutput.GetError() )
225 : : {
226 [ # # ]: 0 : if ( eFormat == EE_FORMAT_TEXT )
227 [ # # ]: 0 : WriteText( rOutput, aSel );
228 [ # # ]: 0 : else if ( eFormat == EE_FORMAT_RTF )
229 [ # # ]: 0 : WriteRTF( rOutput, aSel );
230 [ # # ]: 0 : else if ( eFormat == EE_FORMAT_XML )
231 [ # # ]: 0 : WriteXML( rOutput, aSel );
232 [ # # ]: 0 : else if ( eFormat == EE_FORMAT_HTML )
233 : 0 : WriteHTML( rOutput, aSel );
234 [ # # ]: 0 : else if ( eFormat == EE_FORMAT_BIN)
235 [ # # ]: 0 : WriteBin( rOutput, aSel );
236 : : else
237 : : {
238 : : OSL_FAIL( "Write: Unknown Format" );
239 : : }
240 : : }
241 : 0 : }
242 : :
243 : 0 : sal_uInt32 ImpEditEngine::WriteText( SvStream& rOutput, EditSelection aSel )
244 : : {
245 : : sal_uInt16 nStartNode, nEndNode;
246 : 0 : sal_Bool bRange = aSel.HasRange();
247 [ # # ]: 0 : if ( bRange )
248 : : {
249 : 0 : aSel.Adjust( aEditDoc );
250 : 0 : nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
251 : 0 : nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
252 : : }
253 : : else
254 : : {
255 : 0 : nStartNode = 0;
256 : 0 : nEndNode = aEditDoc.Count()-1;
257 : : }
258 : :
259 : : // iterate over the paragraphs ...
260 [ # # ]: 0 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
261 : : {
262 [ # # ]: 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
263 : : DBG_ASSERT( pNode, "Node not founden: Search&Replace" );
264 : :
265 : 0 : sal_uInt16 nStartPos = 0;
266 [ # # ]: 0 : sal_uInt16 nEndPos = pNode->Len();
267 [ # # ]: 0 : if ( bRange )
268 : : {
269 [ # # ]: 0 : if ( nNode == nStartNode )
270 : 0 : nStartPos = aSel.Min().GetIndex();
271 [ # # ]: 0 : if ( nNode == nEndNode ) // can also be == nStart!
272 : 0 : nEndPos = aSel.Max().GetIndex();
273 : : }
274 [ # # ]: 0 : XubString aTmpStr = aEditDoc.GetParaAsString( pNode, nStartPos, nEndPos );
275 [ # # ]: 0 : rOutput.WriteByteStringLine( aTmpStr, rOutput.GetStreamCharSet() );
276 [ # # ]: 0 : }
277 : :
278 : 0 : return rOutput.GetError();
279 : : }
280 : :
281 : 0 : sal_Bool ImpEditEngine::WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
282 : : std::vector<SvxFontItem*>& rFontTable, SvxColorList& rColorList )
283 : : {
284 : 0 : const SfxPoolItem* pAttrItem = rLst.First();
285 [ # # ]: 0 : while ( pAttrItem )
286 : : {
287 : 0 : WriteItemAsRTF( *pAttrItem, rOutput, nPara, nPos,rFontTable, rColorList );
288 : 0 : pAttrItem = rLst.Next();
289 : : }
290 [ # # ]: 0 : return ( rLst.Count() ? sal_True : sal_False );
291 : : }
292 : :
293 : 0 : void lcl_FindValidAttribs( ItemList& rLst, ContentNode* pNode, sal_uInt16 nIndex, sal_uInt16 nScriptType )
294 : : {
295 : 0 : sal_uInt16 nAttr = 0;
296 : 0 : EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
297 [ # # ][ # # ]: 0 : while ( pAttr && ( pAttr->GetStart() <= nIndex ) )
[ # # ]
298 : : {
299 : : // Start is checked in while ...
300 [ # # ]: 0 : if ( pAttr->GetEnd() > nIndex )
301 : : {
302 [ # # ]: 0 : if ( IsScriptItemValid( pAttr->GetItem()->Which(), nScriptType ) )
303 : 0 : rLst.Insert( pAttr->GetItem() );
304 : : }
305 : 0 : nAttr++;
306 : 0 : pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
307 : : }
308 : 0 : }
309 : :
310 : 0 : sal_uInt32 ImpEditEngine::WriteBin( SvStream& rOutput, EditSelection aSel, sal_Bool bStoreUnicodeStrings )
311 : : {
312 [ # # ]: 0 : BinTextObject* pObj = (BinTextObject*)CreateBinTextObject( aSel, NULL );
313 : 0 : pObj->StoreUnicodeStrings( bStoreUnicodeStrings );
314 : 0 : pObj->Store( rOutput );
315 [ # # ]: 0 : delete pObj;
316 : 0 : return 0;
317 : : }
318 : :
319 : 0 : sal_uInt32 ImpEditEngine::WriteXML( SvStream& rOutput, EditSelection aSel )
320 : : {
321 [ # # ]: 0 : ESelection aESel = CreateESel( aSel );
322 : :
323 [ # # ]: 0 : SvxWriteXML( *GetEditEnginePtr(), rOutput, aESel );
324 : :
325 : 0 : return 0;
326 : : }
327 : :
328 : 0 : static sal_uInt16 getStylePos( const SfxStyles& rStyles, SfxStyleSheet* pSheet )
329 : : {
330 : 0 : sal_uInt16 nNumber = 0;
331 : 0 : SfxStyles::const_iterator iter( rStyles.begin() );
332 [ # # ][ # # ]: 0 : while( iter != rStyles.end() )
333 : : {
334 [ # # ][ # # ]: 0 : if( (*iter++).get() == pSheet )
335 : 0 : return nNumber;
336 : 0 : ++nNumber;
337 : : }
338 : 0 : return 0;
339 : : }
340 : :
341 : 0 : sal_uInt32 ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel )
342 : : {
343 : : DBG_ASSERT( GetUpdateMode(), "WriteRTF for UpdateMode = sal_False!" );
344 [ # # ]: 0 : CheckIdleFormatter();
345 [ # # ]: 0 : if ( !IsFormatted() )
346 [ # # ]: 0 : FormatDoc();
347 : :
348 : : sal_uInt16 nStartNode, nEndNode;
349 [ # # ]: 0 : aSel.Adjust( aEditDoc );
350 : :
351 [ # # ][ # # ]: 0 : nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
352 [ # # ][ # # ]: 0 : nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
353 : :
354 : : // RTF header ...
355 [ # # ]: 0 : rOutput << '{' ;
356 : :
357 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_RTF;
358 : :
359 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_ANSI;
360 : 0 : rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_MS_1252;
361 : :
362 : : // Generate and write out Font table ...
363 [ # # ]: 0 : std::vector<SvxFontItem*> aFontTable;
364 : : // default font must be up front, so DEF font in RTF
365 [ # # ][ # # ]: 0 : aFontTable.push_back( new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO ) ) );
[ # # ][ # # ]
366 [ # # ][ # # ]: 0 : aFontTable.push_back( new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CJK ) ) );
[ # # ][ # # ]
367 [ # # ][ # # ]: 0 : aFontTable.push_back( new SvxFontItem( (const SvxFontItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CTL ) ) );
[ # # ][ # # ]
368 [ # # ]: 0 : for ( sal_uInt16 nScriptType = 0; nScriptType < 3; nScriptType++ )
369 : : {
370 : 0 : sal_uInt16 nWhich = EE_CHAR_FONTINFO;
371 [ # # ]: 0 : if ( nScriptType == 1 )
372 : 0 : nWhich = EE_CHAR_FONTINFO_CJK;
373 [ # # ]: 0 : else if ( nScriptType == 2 )
374 : 0 : nWhich = EE_CHAR_FONTINFO_CTL;
375 : :
376 : 0 : sal_uInt32 i = 0;
377 [ # # ]: 0 : SvxFontItem* pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem2( nWhich, i );
378 [ # # ]: 0 : while ( pFontItem )
379 : : {
380 : 0 : bool bAlreadyExist = false;
381 [ # # ]: 0 : sal_uLong nTestMax = nScriptType ? aFontTable.size() : 1;
382 [ # # ][ # # ]: 0 : for ( sal_uLong nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ )
[ # # ]
383 : : {
384 [ # # ][ # # ]: 0 : bAlreadyExist = *aFontTable[ nTest ] == *pFontItem;
385 : : }
386 : :
387 [ # # ]: 0 : if ( !bAlreadyExist )
388 [ # # ][ # # ]: 0 : aFontTable.push_back( new SvxFontItem( *pFontItem ) );
[ # # ]
389 : :
390 [ # # ]: 0 : pFontItem = (SvxFontItem*)aEditDoc.GetItemPool().GetItem2( nWhich, ++i );
391 : : }
392 : : }
393 : :
394 [ # # ][ # # ]: 0 : rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
[ # # ]
395 : : sal_uInt16 j;
396 [ # # ]: 0 : for ( j = 0; j < aFontTable.size(); j++ )
397 : : {
398 [ # # ]: 0 : SvxFontItem* pFontItem = aFontTable[ j ];
399 [ # # ]: 0 : rOutput << '{';
400 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_F;
401 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>( j ) );
402 [ # # # # : 0 : switch ( pFontItem->GetFamily() )
# # # ]
403 : : {
404 [ # # ]: 0 : case FAMILY_DONTKNOW: rOutput << OOO_STRING_SVTOOLS_RTF_FNIL;
405 : 0 : break;
406 [ # # ]: 0 : case FAMILY_DECORATIVE: rOutput << OOO_STRING_SVTOOLS_RTF_FDECOR;
407 : 0 : break;
408 [ # # ]: 0 : case FAMILY_MODERN: rOutput << OOO_STRING_SVTOOLS_RTF_FMODERN;
409 : 0 : break;
410 [ # # ]: 0 : case FAMILY_ROMAN: rOutput << OOO_STRING_SVTOOLS_RTF_FROMAN;
411 : 0 : break;
412 [ # # ]: 0 : case FAMILY_SCRIPT: rOutput << OOO_STRING_SVTOOLS_RTF_FSCRIPT;
413 : 0 : break;
414 [ # # ]: 0 : case FAMILY_SWISS: rOutput << OOO_STRING_SVTOOLS_RTF_FSWISS;
415 : 0 : break;
416 : : default:
417 : 0 : break;
418 : : }
419 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_FPRQ;
420 : 0 : sal_uInt16 nVal = 0;
421 [ # # # ]: 0 : switch( pFontItem->GetPitch() )
422 : : {
423 : 0 : case PITCH_FIXED: nVal = 1; break;
424 : 0 : case PITCH_VARIABLE: nVal = 2; break;
425 : : default:
426 : 0 : break;
427 : : }
428 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>( nVal ) );
429 : :
430 : 0 : CharSet eChrSet = pFontItem->GetCharSet();
431 : : DBG_ASSERT( eChrSet != 9, "SystemCharSet?!" );
432 [ # # ]: 0 : if( RTL_TEXTENCODING_DONTKNOW == eChrSet )
433 [ # # ]: 0 : eChrSet = osl_getThreadTextEncoding();
434 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_FCHARSET;
435 [ # # ][ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) ) );
436 : :
437 [ # # ]: 0 : rOutput << ' ';
438 [ # # ]: 0 : RTFOutFuncs::Out_String( rOutput, pFontItem->GetFamilyName(), eDestEnc );
439 [ # # ]: 0 : rOutput << ";}";
440 : : }
441 [ # # ]: 0 : rOutput << '}';
442 [ # # ]: 0 : rOutput << endl;
443 : :
444 : : // Write out ColorList ...
445 [ # # ]: 0 : SvxColorList aColorList;
446 : 0 : sal_uInt32 i = 0;
447 [ # # ]: 0 : SvxColorItem* pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem2( EE_CHAR_COLOR, i );
448 [ # # ]: 0 : while ( pColorItem )
449 : : {
450 : 0 : sal_uInt32 nPos = i;
451 [ # # ]: 0 : if ( pColorItem->GetValue() == COL_AUTO )
452 : 0 : nPos = 0;
453 [ # # ][ # # ]: 0 : aColorList.Insert( new SvxColorItem( *pColorItem ), nPos );
[ # # ]
454 [ # # ]: 0 : pColorItem = (SvxColorItem*)aEditDoc.GetItemPool().GetItem2( EE_CHAR_COLOR, ++i );
455 : : }
456 [ # # ][ # # ]: 0 : aColorList.Insert( new SvxColorItem( (const SvxColorItem&)aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_COLOR) ), i );
[ # # ][ # # ]
457 : :
458 [ # # ][ # # ]: 0 : rOutput << '{' << OOO_STRING_SVTOOLS_RTF_COLORTBL;
459 [ # # ]: 0 : for ( j = 0; j < aColorList.Count(); j++ )
460 : : {
461 [ # # ]: 0 : pColorItem = aColorList.GetObject( j );
462 [ # # ][ # # ]: 0 : if ( !j || ( pColorItem->GetValue() != COL_AUTO ) )
[ # # ][ # # ]
463 : : {
464 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_RED;
465 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>(pColorItem->GetValue().GetRed()) );
466 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_GREEN;
467 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>(pColorItem->GetValue().GetGreen()) );
468 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_BLUE;
469 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>(pColorItem->GetValue().GetBlue()) );
470 : : }
471 [ # # ]: 0 : rOutput << ';';
472 : : }
473 [ # # ]: 0 : rOutput << '}';
474 [ # # ]: 0 : rOutput << endl;
475 : :
476 : : // StyleSheets...
477 [ # # ]: 0 : if ( GetStyleSheetPool() )
478 : : {
479 [ # # ]: 0 : sal_uInt16 nStyles = (sal_uInt16)GetStyleSheetPool()->GetStyles().size();
480 [ # # ]: 0 : if ( nStyles )
481 : : {
482 [ # # ][ # # ]: 0 : rOutput << '{' << OOO_STRING_SVTOOLS_RTF_STYLESHEET;
483 : :
484 [ # # ]: 0 : for ( sal_uInt16 nStyle = 0; nStyle < nStyles; nStyle++ )
485 : : {
486 : :
487 [ # # ]: 0 : SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->GetStyles()[ nStyle ].get();
488 : :
489 [ # # ][ # # ]: 0 : rOutput << endl << '{' << OOO_STRING_SVTOOLS_RTF_S;
[ # # ]
490 : 0 : sal_uInt32 nNumber = nStyle + 1;
491 [ # # ]: 0 : rOutput.WriteNumber( nNumber );
492 : :
493 : : // Attribute, alos from Parent!
494 [ # # ]: 0 : for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
495 : : {
496 [ # # ][ # # ]: 0 : if ( pStyle->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
[ # # ]
497 : : {
498 [ # # ][ # # ]: 0 : const SfxPoolItem& rItem = pStyle->GetItemSet().Get( nParAttr );
499 [ # # ]: 0 : WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
500 : : }
501 : : }
502 : :
503 : : // Parent ... (only if necessary)
504 [ # # ][ # # ]: 0 : if ( pStyle->GetParent().Len() && ( pStyle->GetParent() != pStyle->GetName() ) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
505 : : {
506 [ # # ][ # # ]: 0 : SfxStyleSheet* pParent = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetParent(), pStyle->GetFamily() );
507 : : DBG_ASSERT( pParent, "Parent not found!" );
508 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SBASEDON;
509 [ # # ][ # # ]: 0 : nNumber = getStylePos( GetStyleSheetPool()->GetStyles(), pParent ) + 1;
510 [ # # ]: 0 : rOutput.WriteNumber( nNumber );
511 : : }
512 : :
513 : : // Next Style ... (more)
514 : 0 : SfxStyleSheet* pNext = pStyle;
515 [ # # ][ # # ]: 0 : if ( pStyle->GetFollow().Len() && ( pStyle->GetFollow() != pStyle->GetName() ) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
516 [ # # ][ # # ]: 0 : pNext = (SfxStyleSheet*)GetStyleSheetPool()->Find( pStyle->GetFollow(), pStyle->GetFamily() );
517 : :
518 : : DBG_ASSERT( pNext, "Next ot found!" );
519 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SNEXT;
520 [ # # ][ # # ]: 0 : nNumber = getStylePos( GetStyleSheetPool()->GetStyles(), pNext ) + 1;
521 [ # # ]: 0 : rOutput.WriteNumber( nNumber );
522 : :
523 : : // Name of the template ...
524 [ # # ][ # # ]: 0 : rOutput << " " << rtl::OUStringToOString(pStyle->GetName(), eDestEnc).getStr();
[ # # ][ # # ]
[ # # ]
525 [ # # ]: 0 : rOutput << ";}";
526 : : }
527 [ # # ]: 0 : rOutput << '}';
528 [ # # ]: 0 : rOutput << endl;
529 : : }
530 : : }
531 : :
532 : : // Write the pool defaults in advance ...
533 [ # # ][ # # ]: 0 : rOutput << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << "\\EditEnginePoolDefaults";
[ # # ]
534 [ # # ]: 0 : for ( sal_uInt16 nPoolDefItem = EE_PARA_START; nPoolDefItem <= EE_CHAR_END; nPoolDefItem++)
535 : : {
536 [ # # ]: 0 : const SfxPoolItem& rItem = aEditDoc.GetItemPool().GetDefaultItem( nPoolDefItem );
537 [ # # ]: 0 : WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList );
538 : : }
539 [ # # ][ # # ]: 0 : rOutput << '}' << endl;
540 : :
541 : : // DefTab:
542 [ # # ]: 0 : MapMode aTwpMode( MAP_TWIP );
543 : : sal_uInt16 nDefTabTwps = (sal_uInt16) GetRefDevice()->LogicToLogic(
544 : 0 : Point( aEditDoc.GetDefTab(), 0 ),
545 [ # # ]: 0 : &GetRefMapMode(), &aTwpMode ).X();
546 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_DEFTAB;
547 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>( nDefTabTwps ) );
548 [ # # ]: 0 : rOutput << endl;
549 : :
550 : : // iterate over the paragraphs ...
551 [ # # ][ # # ]: 0 : rOutput << '{' << endl;
552 [ # # ]: 0 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
553 : : {
554 [ # # ]: 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
555 : : DBG_ASSERT( pNode, "Node not found: Search&Replace" );
556 : :
557 : : // The paragraph attributes in advance ...
558 : 0 : sal_Bool bAttr = sal_False;
559 : :
560 : : // Template?
561 [ # # ]: 0 : if ( pNode->GetStyleSheet() )
562 : : {
563 : : // Number of template
564 [ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_S;
565 [ # # ][ # # ]: 0 : sal_uInt32 nNumber = getStylePos( GetStyleSheetPool()->GetStyles(), pNode->GetStyleSheet() ) + 1;
566 [ # # ]: 0 : rOutput.WriteNumber( nNumber );
567 : :
568 : : // All Attribute
569 : : // Attribute, also from Parent!
570 [ # # ]: 0 : for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
571 : : {
572 [ # # ][ # # ]: 0 : if ( pNode->GetStyleSheet()->GetItemSet().GetItemState( nParAttr ) == SFX_ITEM_ON )
[ # # ]
573 : : {
574 [ # # ][ # # ]: 0 : const SfxPoolItem& rItem = pNode->GetStyleSheet()->GetItemSet().Get( nParAttr );
575 [ # # ]: 0 : WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
576 : 0 : bAttr = sal_True;
577 : : }
578 : : }
579 : : }
580 : :
581 [ # # ]: 0 : for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ )
582 : : {
583 : : // Now where stylesheet processing, only hard paragraph attributes!
584 [ # # ][ # # ]: 0 : if ( pNode->GetContentAttribs().GetItems().GetItemState( nParAttr ) == SFX_ITEM_ON )
585 : : {
586 [ # # ]: 0 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nParAttr );
587 [ # # ]: 0 : WriteItemAsRTF( rItem, rOutput, nNode, 0, aFontTable, aColorList );
588 : 0 : bAttr = sal_True;
589 : : }
590 : : }
591 [ # # ]: 0 : if ( bAttr )
592 [ # # ]: 0 : rOutput << ' '; // Separator
593 : :
594 [ # # ]: 0 : ItemList aAttribItems;
595 [ # # ]: 0 : ParaPortion* pParaPortion = FindParaPortion( pNode );
596 : : DBG_ASSERT( pParaPortion, "Portion not found: WriteRTF" );
597 : :
598 : 0 : sal_uInt16 nIndex = 0;
599 : 0 : sal_uInt16 nStartPos = 0;
600 [ # # ]: 0 : sal_uInt16 nEndPos = pNode->Len();
601 : 0 : sal_uInt16 nStartPortion = 0;
602 [ # # ]: 0 : sal_uInt16 nEndPortion = (sal_uInt16)pParaPortion->GetTextPortions().Count() - 1;
603 : 0 : sal_Bool bFinishPortion = sal_False;
604 : : sal_uInt16 nPortionStart;
605 : :
606 [ # # ]: 0 : if ( nNode == nStartNode )
607 : : {
608 : 0 : nStartPos = aSel.Min().GetIndex();
609 [ # # ]: 0 : nStartPortion = pParaPortion->GetTextPortions().FindPortion( nStartPos, nPortionStart );
610 [ # # ]: 0 : if ( nStartPos != 0 )
611 : : {
612 : 0 : aAttribItems.Clear();
613 [ # # ][ # # ]: 0 : lcl_FindValidAttribs( aAttribItems, pNode, nStartPos, GetScriptType( EditPaM( pNode, 0 ) ) );
[ # # ]
614 [ # # ]: 0 : if ( aAttribItems.Count() )
615 : : {
616 : : // These attributes may not apply to the entire paragraph:
617 [ # # ]: 0 : rOutput << '{';
618 [ # # ]: 0 : WriteItemListAsRTF( aAttribItems, rOutput, nNode, nStartPos, aFontTable, aColorList );
619 : 0 : bFinishPortion = sal_True;
620 : : }
621 : 0 : aAttribItems.Clear();
622 : : }
623 : : }
624 [ # # ]: 0 : if ( nNode == nEndNode ) // can also be == nStart!
625 : : {
626 : 0 : nEndPos = aSel.Max().GetIndex();
627 [ # # ]: 0 : nEndPortion = pParaPortion->GetTextPortions().FindPortion( nEndPos, nPortionStart );
628 : : }
629 : :
630 [ # # ]: 0 : const EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature(nIndex);
631 : : // start at 0, so the index is right ...
632 [ # # ]: 0 : for ( sal_uInt16 n = 0; n <= nEndPortion; n++ )
633 : : {
634 [ # # ]: 0 : const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[n];
635 [ # # ]: 0 : if ( n < nStartPortion )
636 : : {
637 : 0 : nIndex = nIndex + pTextPortion->GetLen();
638 : 0 : continue;
639 : : }
640 : :
641 [ # # ][ # # ]: 0 : if ( pNextFeature && ( pNextFeature->GetStart() == nIndex ) && ( pNextFeature->GetItem()->Which() != EE_FEATURE_FIELD ) )
[ # # ][ # # ]
642 : : {
643 [ # # ]: 0 : WriteItemAsRTF( *pNextFeature->GetItem(), rOutput, nNode, nIndex, aFontTable, aColorList );
644 [ # # ]: 0 : pNextFeature = pNode->GetCharAttribs().FindFeature( pNextFeature->GetStart() + 1 );
645 : : }
646 : : else
647 : : {
648 : 0 : aAttribItems.Clear();
649 [ # # ][ # # ]: 0 : sal_uInt16 nScriptType = GetScriptType( EditPaM( pNode, nIndex+1 ) );
650 [ # # ][ # # ]: 0 : if ( !n || IsScriptChange( EditPaM( pNode, nIndex ) ) )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
651 : : {
652 [ # # ]: 0 : SfxItemSet aAttribs = GetAttribs( nNode, nIndex+1, nIndex+1 );
653 [ # # ][ # # ]: 0 : aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ) ) );
[ # # ]
654 [ # # ][ # # ]: 0 : aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ) ) );
[ # # ]
655 [ # # ][ # # ]: 0 : aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ) ) );
[ # # ]
656 [ # # ][ # # ]: 0 : aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_ITALIC, nScriptType ) ) );
[ # # ]
657 [ # # ][ # # ]: 0 : aAttribItems.Insert( &aAttribs.Get( GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ) ) );
[ # # ][ # # ]
658 : : }
659 : : // Insert hard attribs AFTER CJK attribs...
660 [ # # ]: 0 : lcl_FindValidAttribs( aAttribItems, pNode, nIndex, nScriptType );
661 : :
662 [ # # ]: 0 : rOutput << '{';
663 [ # # ][ # # ]: 0 : if ( WriteItemListAsRTF( aAttribItems, rOutput, nNode, nIndex, aFontTable, aColorList ) )
664 [ # # ]: 0 : rOutput << ' ';
665 : :
666 : 0 : sal_uInt16 nS = nIndex;
667 : 0 : sal_uInt16 nE = nIndex + pTextPortion->GetLen();
668 [ # # ]: 0 : if ( n == nStartPortion )
669 : 0 : nS = nStartPos;
670 [ # # ]: 0 : if ( n == nEndPortion )
671 : 0 : nE = nEndPos;
672 : :
673 [ # # ]: 0 : XubString aRTFStr = aEditDoc.GetParaAsString( pNode, nS, nE);
674 [ # # ]: 0 : RTFOutFuncs::Out_String( rOutput, aRTFStr, eDestEnc );
675 [ # # ][ # # ]: 0 : rOutput << '}';
676 : : }
677 [ # # ]: 0 : if ( bFinishPortion )
678 : : {
679 [ # # ]: 0 : rOutput << '}';
680 : 0 : bFinishPortion = sal_False;
681 : : }
682 : :
683 : 0 : nIndex = nIndex + pTextPortion->GetLen();
684 : : }
685 : :
686 [ # # ][ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_PAR << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_PLAIN;;
[ # # ]
687 [ # # ]: 0 : rOutput << endl;
688 : 0 : }
689 : : // RTF-trailer ...
690 [ # # ]: 0 : rOutput << "}}"; // 1xparentheses paragraphs, 1xparentheses RTF document
691 [ # # ]: 0 : rOutput.Flush();
692 : :
693 : 0 : std::vector<SvxFontItem*>::iterator it;
694 [ # # ][ # # ]: 0 : for (it = aFontTable.begin(); it != aFontTable.end(); ++it)
695 [ # # ][ # # ]: 0 : delete *it;
696 : :
697 : : #if (OSL_DEBUG_LEVEL > 2) && !defined( UNX )
698 : : {
699 : : SvFileStream aStream( String( RTL_CONSTASCII_USTRINGPARAM ( "d:\\rtf_out.rtf" ) ), STREAM_WRITE|STREAM_TRUNC );
700 : : sal_uLong nP = rOutput.Tell();
701 : : rOutput.Seek( 0 );
702 : : aStream << rOutput;
703 : : rOutput.Seek( nP );
704 : : }
705 : : #endif
706 : :
707 [ # # ][ # # ]: 0 : return rOutput.GetError();
708 : : }
709 : :
710 : :
711 : 0 : void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_uInt16 nPara, sal_uInt16 nPos,
712 : : std::vector<SvxFontItem*>& rFontTable, SvxColorList& rColorList )
713 : : {
714 : 0 : sal_uInt16 nWhich = rItem.Which();
715 [ # # # # : 0 : switch ( nWhich )
# # # # #
# # # # #
# # # # #
# # # # #
# ]
716 : : {
717 : : case EE_PARA_WRITINGDIR:
718 : : {
719 : 0 : const SvxFrameDirectionItem& rWritingMode = (const SvxFrameDirectionItem&)rItem;
720 [ # # ]: 0 : if ( rWritingMode.GetValue() == FRMDIR_HORI_RIGHT_TOP )
721 : 0 : rOutput << "\\rtlpar";
722 : : else
723 : 0 : rOutput << "\\ltrpar";
724 : : }
725 : 0 : break;
726 : : case EE_PARA_OUTLLEVEL:
727 : : {
728 : 0 : sal_Int32 nLevel = ((const SfxInt16Item&)rItem).GetValue();
729 [ # # ]: 0 : if( nLevel >= 0 )
730 : : {
731 : 0 : rOutput << "\\level";
732 : 0 : rOutput.WriteNumber( nLevel );
733 : : }
734 : : }
735 : 0 : break;
736 : : case EE_PARA_OUTLLRSPACE:
737 : : case EE_PARA_LRSPACE:
738 : : {
739 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_FI;
740 : 0 : sal_Int32 nTxtFirst = ((const SvxLRSpaceItem&)rItem).GetTxtFirstLineOfst();
741 : 0 : nTxtFirst = LogicToTwips( nTxtFirst );
742 : 0 : rOutput.WriteNumber( nTxtFirst );
743 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_LI;
744 : 0 : sal_uInt32 nTxtLeft = static_cast< sal_uInt32 >(((const SvxLRSpaceItem&)rItem).GetTxtLeft());
745 : 0 : nTxtLeft = (sal_uInt32)LogicToTwips( nTxtLeft );
746 : 0 : rOutput.WriteNumber( nTxtLeft );
747 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_RI;
748 : 0 : sal_uInt32 nTxtRight = ((const SvxLRSpaceItem&)rItem).GetRight();
749 : 0 : nTxtRight = LogicToTwips( nTxtRight);
750 : 0 : rOutput.WriteNumber( nTxtRight );
751 : : }
752 : 0 : break;
753 : : case EE_PARA_ULSPACE:
754 : : {
755 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SB;
756 : 0 : sal_uInt32 nUpper = ((const SvxULSpaceItem&)rItem).GetUpper();
757 : 0 : nUpper = (sal_uInt32)LogicToTwips( nUpper );
758 : 0 : rOutput.WriteNumber( nUpper );
759 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SA;
760 : 0 : sal_uInt32 nLower = ((const SvxULSpaceItem&)rItem).GetLower();
761 : 0 : nLower = LogicToTwips( nLower );
762 : 0 : rOutput.WriteNumber( nLower );
763 : : }
764 : 0 : break;
765 : : case EE_PARA_SBL:
766 : : {
767 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SL;
768 : 0 : sal_Int32 nVal = ((const SvxLineSpacingItem&)rItem).GetLineHeight();
769 : 0 : char cMult = '0';
770 [ # # ]: 0 : if ( ((const SvxLineSpacingItem&)rItem).GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP )
771 : : {
772 : : // From where do I get the value now?
773 : : // The SwRTF parser is based on a 240 Font!
774 : 0 : nVal = ((const SvxLineSpacingItem&)rItem).GetPropLineSpace();
775 : 0 : nVal *= 240;
776 : 0 : nVal /= 100;
777 : 0 : cMult = '1';
778 : : }
779 : 0 : rOutput.WriteNumber( nVal );
780 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SLMULT << cMult;
781 : : }
782 : 0 : break;
783 : : case EE_PARA_JUST:
784 : : {
785 : 0 : SvxAdjust eJustification = ((const SvxAdjustItem&)rItem).GetAdjust();
786 [ # # # ]: 0 : switch ( eJustification )
787 : : {
788 : 0 : case SVX_ADJUST_CENTER: rOutput << OOO_STRING_SVTOOLS_RTF_QC;
789 : 0 : break;
790 : 0 : case SVX_ADJUST_RIGHT: rOutput << OOO_STRING_SVTOOLS_RTF_QR;
791 : 0 : break;
792 : 0 : default: rOutput << OOO_STRING_SVTOOLS_RTF_QL;
793 : 0 : break;
794 : : }
795 : : }
796 : 0 : break;
797 : : case EE_PARA_TABS:
798 : : {
799 : 0 : const SvxTabStopItem& rTabs = (const SvxTabStopItem&) rItem;
800 [ # # ]: 0 : for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
801 : : {
802 : 0 : const SvxTabStop& rTab = rTabs[i];
803 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_TX;
804 : 0 : rOutput.WriteNumber( LogicToTwips( rTab.GetTabPos() ) );
805 : : }
806 : : }
807 : 0 : break;
808 : : case EE_CHAR_COLOR:
809 : : {
810 : 0 : sal_uInt32 n = rColorList.GetId( (const SvxColorItem&)rItem );
811 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_CF;
812 : 0 : rOutput.WriteNumber( n );
813 : : }
814 : 0 : break;
815 : : case EE_CHAR_FONTINFO:
816 : : case EE_CHAR_FONTINFO_CJK:
817 : : case EE_CHAR_FONTINFO_CTL:
818 : : {
819 : 0 : sal_uInt32 n = 0;
820 [ # # ]: 0 : for (size_t i = 0; i < rFontTable.size(); ++i)
821 : : {
822 [ # # ]: 0 : if (*rFontTable[i] == rItem)
823 : : {
824 : 0 : n = i;
825 : 0 : break;
826 : : }
827 : : }
828 : :
829 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_F;
830 : 0 : rOutput.WriteNumber( n );
831 : : }
832 : 0 : break;
833 : : case EE_CHAR_FONTHEIGHT:
834 : : case EE_CHAR_FONTHEIGHT_CJK:
835 : : case EE_CHAR_FONTHEIGHT_CTL:
836 : : {
837 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_FS;
838 : 0 : sal_Int32 nHeight = ((const SvxFontHeightItem&)rItem).GetHeight();
839 : 0 : nHeight = LogicToTwips( nHeight );
840 : : // Twips => HalfPoints
841 : 0 : nHeight /= 10;
842 : 0 : rOutput.WriteNumber( nHeight );
843 : : }
844 : 0 : break;
845 : : case EE_CHAR_WEIGHT:
846 : : case EE_CHAR_WEIGHT_CJK:
847 : : case EE_CHAR_WEIGHT_CTL:
848 : : {
849 : 0 : FontWeight e = ((const SvxWeightItem&)rItem).GetWeight();
850 [ # # ]: 0 : switch ( e )
851 : : {
852 : 0 : case WEIGHT_BOLD: rOutput << OOO_STRING_SVTOOLS_RTF_B; break;
853 : 0 : default: rOutput << OOO_STRING_SVTOOLS_RTF_B << '0'; break;
854 : : }
855 : : }
856 : 0 : break;
857 : : case EE_CHAR_UNDERLINE:
858 : : {
859 : : // Must underlined if in WordLineMode, but the information is
860 : : // missing here
861 : 0 : FontUnderline e = ((const SvxUnderlineItem&)rItem).GetLineStyle();
862 [ # # # # : 0 : switch ( e )
# ]
863 : : {
864 : 0 : case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_ULNONE; break;
865 : 0 : case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_UL; break;
866 : 0 : case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_ULDB; break;
867 : 0 : case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_ULD; break;
868 : : default:
869 : 0 : break;
870 : : }
871 : : }
872 : 0 : break;
873 : : case EE_CHAR_OVERLINE:
874 : : {
875 : 0 : FontUnderline e = ((const SvxOverlineItem&)rItem).GetLineStyle();
876 [ # # # # : 0 : switch ( e )
# ]
877 : : {
878 : 0 : case UNDERLINE_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_OLNONE; break;
879 : 0 : case UNDERLINE_SINGLE: rOutput << OOO_STRING_SVTOOLS_RTF_OL; break;
880 : 0 : case UNDERLINE_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_OLDB; break;
881 : 0 : case UNDERLINE_DOTTED: rOutput << OOO_STRING_SVTOOLS_RTF_OLD; break;
882 : : default:
883 : 0 : break;
884 : : }
885 : : }
886 : 0 : break;
887 : : case EE_CHAR_STRIKEOUT:
888 : : {
889 : 0 : FontStrikeout e = ((const SvxCrossedOutItem&)rItem).GetStrikeout();
890 [ # # # ]: 0 : switch ( e )
891 : : {
892 : : case STRIKEOUT_SINGLE:
893 : 0 : case STRIKEOUT_DOUBLE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE; break;
894 : 0 : case STRIKEOUT_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_STRIKE << '0'; break;
895 : : default:
896 : 0 : break;
897 : : }
898 : : }
899 : 0 : break;
900 : : case EE_CHAR_ITALIC:
901 : : case EE_CHAR_ITALIC_CJK:
902 : : case EE_CHAR_ITALIC_CTL:
903 : : {
904 : 0 : FontItalic e = ((const SvxPostureItem&)rItem).GetPosture();
905 [ # # # ]: 0 : switch ( e )
906 : : {
907 : : case ITALIC_OBLIQUE:
908 : 0 : case ITALIC_NORMAL: rOutput << OOO_STRING_SVTOOLS_RTF_I; break;
909 : 0 : case ITALIC_NONE: rOutput << OOO_STRING_SVTOOLS_RTF_I << '0'; break;
910 : : default:
911 : 0 : break;
912 : : }
913 : : }
914 : 0 : break;
915 : : case EE_CHAR_OUTLINE:
916 : : {
917 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_OUTL;
918 [ # # ]: 0 : if ( ((const SvxContourItem&)rItem).GetValue() == 0 )
919 : 0 : rOutput << '0';
920 : : }
921 : 0 : break;
922 : : case EE_CHAR_RELIEF:
923 : : {
924 : 0 : sal_uInt16 nRelief = ((const SvxCharReliefItem&)rItem).GetValue();
925 [ # # ]: 0 : if ( nRelief == RELIEF_EMBOSSED )
926 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_EMBO;
927 [ # # ]: 0 : if ( nRelief == RELIEF_ENGRAVED )
928 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_IMPR;
929 : : }
930 : 0 : break;
931 : : case EE_CHAR_EMPHASISMARK:
932 : : {
933 : 0 : sal_uInt16 nMark = ((const SvxEmphasisMarkItem&)rItem).GetValue();
934 [ # # ]: 0 : if ( nMark == EMPHASISMARK_NONE )
935 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_ACCNONE;
936 [ # # ]: 0 : else if ( nMark == EMPHASISMARK_SIDE_DOTS )
937 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_ACCCOMMA;
938 : : else
939 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_ACCDOT;
940 : : }
941 : 0 : break;
942 : : case EE_CHAR_SHADOW:
943 : : {
944 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SHAD;
945 [ # # ]: 0 : if ( ((const SvxShadowedItem&)rItem).GetValue() == 0 )
946 : 0 : rOutput << '0';
947 : : }
948 : 0 : break;
949 : : case EE_FEATURE_TAB:
950 : : {
951 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_TAB;
952 : : }
953 : 0 : break;
954 : : case EE_FEATURE_LINEBR:
955 : : {
956 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_SL;
957 : : }
958 : 0 : break;
959 : : case EE_CHAR_KERNING:
960 : : {
961 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_EXPNDTW;
962 : : rOutput.WriteNumber( LogicToTwips(
963 : 0 : ((const SvxKerningItem&)rItem).GetValue() ) );
964 : : }
965 : 0 : break;
966 : : case EE_CHAR_PAIRKERNING:
967 : : {
968 : 0 : rOutput << OOO_STRING_SVTOOLS_RTF_KERNING;
969 [ # # ]: 0 : rOutput.WriteNumber( static_cast<sal_uInt32>(((const SvxAutoKernItem&)rItem).GetValue() ? 1 : 0 ));
970 : : }
971 : 0 : break;
972 : : case EE_CHAR_ESCAPEMENT:
973 : : {
974 [ # # ]: 0 : SvxFont aFont;
975 [ # # ]: 0 : ContentNode* pNode = aEditDoc.GetObject( nPara );
976 [ # # ]: 0 : SeekCursor( pNode, nPos, aFont );
977 [ # # ]: 0 : MapMode aPntMode( MAP_POINT );
978 : : long nFontHeight = GetRefDevice()->LogicToLogic(
979 [ # # ][ # # ]: 0 : aFont.GetSize(), &GetRefMapMode(), &aPntMode ).Height();
980 : 0 : nFontHeight *=2; // HalfP oints
981 : 0 : sal_uInt16 nProp = ((const SvxEscapementItem&)rItem).GetProp();
982 : 0 : sal_uInt16 nProp100 = nProp*100; // For SWG-Token Prop in 100th percent.
983 : 0 : short nEsc = ((const SvxEscapementItem&)rItem).GetEsc();
984 [ # # ]: 0 : if ( nEsc == DFLT_ESC_AUTO_SUPER )
985 : : {
986 : 0 : nEsc = 100 - nProp;
987 : 0 : nProp100++; // A 1 afterwards means 'automatic'.
988 : : }
989 [ # # ]: 0 : else if ( nEsc == DFLT_ESC_AUTO_SUB )
990 : : {
991 : 0 : nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
992 : 0 : nProp100++;
993 : : }
994 : : // SWG:
995 [ # # ]: 0 : if ( nEsc )
996 : : {
997 [ # # ]: 0 : rOutput << "{\\*\\updnprop" << rtl::OString::valueOf(
998 [ # # ][ # # ]: 0 : static_cast<sal_Int32>(nProp100)).getStr() << '}';
999 : : }
1000 : 0 : long nUpDown = nFontHeight * Abs( nEsc ) / 100;
1001 : : rtl::OString aUpDown = rtl::OString::valueOf(
1002 : 0 : static_cast<sal_Int32>(nUpDown));
1003 [ # # ]: 0 : if ( nEsc < 0 )
1004 [ # # ][ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_DN << aUpDown.getStr();
1005 [ # # ]: 0 : else if ( nEsc > 0 )
1006 [ # # ][ # # ]: 0 : rOutput << OOO_STRING_SVTOOLS_RTF_UP << aUpDown.getStr();
[ # # ][ # # ]
1007 : : }
1008 : 0 : break;
1009 : : }
1010 : 0 : }
1011 : :
1012 : 0 : sal_uInt32 ImpEditEngine::WriteHTML( SvStream&, EditSelection )
1013 : : {
1014 : 0 : return 0;
1015 : : }
1016 : :
1017 : :
1018 : 9276 : EditTextObject* ImpEditEngine::CreateTextObject()
1019 : : {
1020 [ + - ]: 9276 : EditSelection aCompleteSelection;
1021 [ + - ][ + - ]: 9276 : aCompleteSelection.Min() = aEditDoc.GetStartPaM();
1022 [ + - ][ + - ]: 9276 : aCompleteSelection.Max() = aEditDoc.GetEndPaM();
1023 : :
1024 [ + - ][ + - ]: 9276 : return CreateTextObject( aCompleteSelection );
1025 : : }
1026 : :
1027 : 63193 : EditTextObject* ImpEditEngine::CreateTextObject( EditSelection aSel )
1028 : : {
1029 [ + - ]: 63193 : return CreateBinTextObject( aSel, GetEditTextObjectPool(), aStatus.AllowBigObjects(), nBigTextObjectStart );
1030 : : }
1031 : :
1032 : 63193 : EditTextObject* ImpEditEngine::CreateBinTextObject( EditSelection aSel, SfxItemPool* pPool, sal_Bool bAllowBigObjects, sal_uInt16 nBigObjectStart )
1033 : : {
1034 [ + - ]: 63193 : BinTextObject* pTxtObj = new BinTextObject( pPool );
1035 : 63193 : pTxtObj->SetVertical( IsVertical() );
1036 : 63193 : MapUnit eMapUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
1037 : 63193 : pTxtObj->SetMetric( (sal_uInt16) eMapUnit );
1038 [ + + ]: 63193 : if ( pTxtObj->IsOwnerOfPool() )
1039 : 8591 : pTxtObj->GetPool()->SetDefaultMetric( (SfxMapUnit) eMapUnit );
1040 : :
1041 : : sal_uInt16 nStartNode, nEndNode;
1042 : 63193 : sal_uInt32 nTextPortions = 0;
1043 : :
1044 : 63193 : aSel.Adjust( aEditDoc );
1045 : 63193 : nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
1046 : 63193 : nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
1047 : :
1048 : 63193 : sal_Bool bOnlyFullParagraphs = ( aSel.Min().GetIndex() ||
1049 : 63193 : ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() ) ) ?
1050 [ + - + - ]: 126386 : sal_False : sal_True;
1051 : :
1052 : : // Templates are not saved!
1053 : : // (Only the name and family, template itself must be in App!)
1054 : 63193 : pTxtObj->SetScriptType( GetScriptType( aSel ) );
1055 : :
1056 : : // iterate over the paragraphs ...
1057 : : sal_uInt16 nNode;
1058 [ + + ]: 132423 : for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
1059 : : {
1060 : 69230 : ContentNode* pNode = aEditDoc.GetObject( nNode );
1061 : : DBG_ASSERT( pNode, "Node not found: Search&Replace" );
1062 : :
1063 [ + - ]: 69230 : if ( bOnlyFullParagraphs )
1064 : : {
1065 : 69230 : const ParaPortion* pParaPortion = GetParaPortions()[nNode];
1066 : 69230 : nTextPortions += pParaPortion->GetTextPortions().Count();
1067 : : }
1068 : :
1069 : 69230 : sal_uInt16 nStartPos = 0;
1070 : 69230 : sal_uInt16 nEndPos = pNode->Len();
1071 : :
1072 : 69230 : sal_Bool bEmptyPara = nEndPos ? sal_False : sal_True;
1073 : :
1074 [ - + ][ + + ]: 69230 : if ( ( nNode == nStartNode ) && !bOnlyFullParagraphs )
1075 : 0 : nStartPos = aSel.Min().GetIndex();
1076 [ + + ][ - + ]: 69230 : if ( ( nNode == nEndNode ) && !bOnlyFullParagraphs )
1077 : 0 : nEndPos = aSel.Max().GetIndex();
1078 : :
1079 : :
1080 : 69230 : ContentInfo* pC = pTxtObj->CreateAndInsertContent();
1081 : :
1082 : : // The paragraph attributes ...
1083 : 69230 : pC->GetParaAttribs().Set( pNode->GetContentAttribs().GetItems() );
1084 : :
1085 : : // The StyleSheet...
1086 [ + + ]: 69230 : if ( pNode->GetStyleSheet() )
1087 : : {
1088 : 8399 : pC->GetStyle() = pNode->GetStyleSheet()->GetName();
1089 : 8399 : pC->GetFamily() = pNode->GetStyleSheet()->GetFamily();
1090 : : }
1091 : :
1092 : : // The Text...
1093 [ + - ]: 69230 : pC->GetText() = pNode->Copy( nStartPos, nEndPos-nStartPos );
1094 : :
1095 : : // and the Attribute...
1096 : 69230 : sal_uInt16 nAttr = 0;
1097 : 69230 : EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1098 [ + + ]: 131604 : while ( pAttr )
1099 : : {
1100 : : // In a blank paragraph keep the attributes!
1101 [ + + + - : 172414 : if ( bEmptyPara ||
+ - ][ + - ]
1102 : 110040 : ( ( pAttr->GetEnd() > nStartPos ) && ( pAttr->GetStart() < nEndPos ) ) )
1103 : : {
1104 : 62374 : XEditAttribute* pX = pTxtObj->CreateAttrib( *pAttr->GetItem(), pAttr->GetStart(), pAttr->GetEnd() );
1105 : : // Possibly Correct ...
1106 [ - + ][ + + ]: 62374 : if ( ( nNode == nStartNode ) && ( nStartPos != 0 ) )
1107 : : {
1108 [ # # ]: 0 : pX->GetStart() = ( pX->GetStart() > nStartPos ) ? pX->GetStart()-nStartPos : 0;
1109 : 0 : pX->GetEnd() = pX->GetEnd() - nStartPos;
1110 : :
1111 : : }
1112 [ + + ]: 62374 : if ( nNode == nEndNode )
1113 : : {
1114 [ - + ]: 37661 : if ( pX->GetEnd() > (nEndPos-nStartPos) )
1115 : 0 : pX->GetEnd() = nEndPos-nStartPos;
1116 : : }
1117 : : DBG_ASSERT( pX->GetEnd() <= (nEndPos-nStartPos), "CreateBinTextObject: Attribute too long!" );
1118 [ + + ][ - + ]: 62374 : if ( !pX->GetLen() && !bEmptyPara )
[ - + ]
1119 : 0 : pTxtObj->DestroyAttrib( pX );
1120 : : else
1121 : 62374 : pC->GetAttribs().push_back(pX);
1122 : : }
1123 : 62374 : nAttr++;
1124 : 62374 : pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1125 : : }
1126 : :
1127 : : // If possible online spelling
1128 [ + + ][ + - ]: 69230 : if ( bAllowBigObjects && bOnlyFullParagraphs && pNode->GetWrongList() )
[ + + ][ + + ]
1129 : 4942 : pC->SetWrongList( pNode->GetWrongList()->Clone() );
1130 : :
1131 : : }
1132 : :
1133 : : // Remember the portions info in case of large text objects:
1134 : : // sleeper set up when Olli paragraphs not hacked!
1135 [ + + ][ + - ]: 63193 : if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && GetUpdateMode() && ( nTextPortions >= nBigObjectStart ) )
[ + + ][ + - ]
[ - + ][ - + ]
1136 : : {
1137 [ # # ]: 0 : XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), aPaperSize.Width(), nStretchX, nStretchY );
1138 : 0 : pTxtObj->SetPortionInfo( pXList );
1139 [ # # ]: 0 : for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
1140 : : {
1141 : 0 : const ParaPortion* pParaPortion = GetParaPortions()[nNode];
1142 [ # # ]: 0 : XParaPortion* pX = new XParaPortion;
1143 : 0 : pXList->push_back(pX);
1144 : :
1145 : 0 : pX->nHeight = pParaPortion->GetHeight();
1146 : 0 : pX->nFirstLineOffset = pParaPortion->GetFirstLineOffset();
1147 : :
1148 : : // The TextPortions
1149 : 0 : sal_uInt16 nCount = pParaPortion->GetTextPortions().Count();
1150 : : sal_uInt16 n;
1151 [ # # ]: 0 : for ( n = 0; n < nCount; n++ )
1152 : : {
1153 : 0 : const TextPortion* pTextPortion = pParaPortion->GetTextPortions()[n];
1154 : 0 : TextPortion* pNew = new TextPortion( *pTextPortion );
1155 : 0 : pX->aTextPortions.Append(pNew);
1156 : : }
1157 : :
1158 : : // The lines
1159 : 0 : nCount = pParaPortion->GetLines().Count();
1160 [ # # ]: 0 : for ( n = 0; n < nCount; n++ )
1161 : : {
1162 : 0 : const EditLine* pLine = pParaPortion->GetLines()[n];
1163 : 0 : EditLine* pNew = pLine->Clone();
1164 : 0 : pX->aLines.Append(pNew);
1165 : : }
1166 : : #ifdef DBG_UTIL
1167 : : sal_uInt16 nTest;
1168 : : int nTPLen = 0, nTxtLen = 0;
1169 : : for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
1170 : : nTPLen += pParaPortion->GetTextPortions()[--nTest]->GetLen();
1171 : : for ( nTest = pParaPortion->GetLines().Count(); nTest; )
1172 : : nTxtLen += pParaPortion->GetLines()[--nTest]->GetLen();
1173 : : DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "CreateBinTextObject: ParaPortion not completely formatted!" );
1174 : : #endif
1175 : : }
1176 : : }
1177 : 63193 : return pTxtObj;
1178 : : }
1179 : :
1180 : 132345 : void ImpEditEngine::SetText( const EditTextObject& rTextObject )
1181 : : {
1182 : : // Since setting a text object is not undo-able!
1183 [ + - ]: 132345 : ResetUndoManager();
1184 : 132345 : sal_Bool _bUpdate = GetUpdateMode();
1185 : 132345 : sal_Bool _bUndo = IsUndoEnabled();
1186 : :
1187 [ + - ][ + - ]: 132345 : SetText( XubString() );
[ + - ]
1188 [ + - ]: 132345 : EditPaM aPaM = aEditDoc.GetStartPaM();
1189 : :
1190 [ + - ]: 132345 : SetUpdateMode( sal_False );
1191 [ + - ]: 132345 : EnableUndo( sal_False );
1192 : :
1193 [ + - ][ + - ]: 132345 : InsertText( rTextObject, EditSelection( aPaM, aPaM ) );
1194 [ + - ][ + - ]: 132345 : SetVertical( rTextObject.IsVertical() );
1195 : :
1196 : : DBG_ASSERT( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "From where comes the Undo in SetText ?!" );
1197 [ + - ]: 132345 : SetUpdateMode( _bUpdate );
1198 [ + - ]: 132345 : EnableUndo( _bUndo );
1199 : 132345 : }
1200 : :
1201 : 132345 : EditSelection ImpEditEngine::InsertText( const EditTextObject& rTextObject, EditSelection aSel )
1202 : : {
1203 : 132345 : EnterBlockNotifications();
1204 : 132345 : aSel.Adjust( aEditDoc );
1205 [ - + ]: 132345 : if ( aSel.HasRange() )
1206 [ # # ]: 0 : aSel = ImpDeleteSelection( aSel );
1207 [ + - ]: 132345 : EditSelection aNewSel = InsertBinTextObject( (BinTextObject&)rTextObject, aSel.Max() );
1208 : 132345 : LeaveBlockNotifications();
1209 : 132345 : return aNewSel;
1210 : : }
1211 : :
1212 : 132345 : EditSelection ImpEditEngine::InsertBinTextObject( BinTextObject& rTextObject, EditPaM aPaM )
1213 : : {
1214 : : // Optimize: No getPos undFindParaportion, instead calculate index!
1215 [ + - ]: 132345 : EditSelection aSel( aPaM, aPaM );
1216 : : DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" );
1217 : :
1218 : 132345 : sal_Bool bUsePortionInfo = sal_False;
1219 : 132345 : XParaPortionList* pPortionInfo = rTextObject.GetPortionInfo();
1220 : :
1221 [ # # ][ # # : 132345 : if ( pPortionInfo && ( (long)pPortionInfo->GetPaperWidth() == aPaperSize.Width() )
# # # # ]
[ - + ][ - + ]
1222 [ # # ]: 0 : && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() )
1223 : 0 : && ( pPortionInfo->GetStretchX() == nStretchX )
1224 : 0 : && ( pPortionInfo->GetStretchY() == nStretchY ) )
1225 : : {
1226 [ # # # # : 0 : if ( ( pPortionInfo->GetRefDevPtr() == (sal_uIntPtr)GetRefDevice() ) ||
# # ][ # # ]
1227 : 0 : ( ( pPortionInfo->GetRefDevType() == OUTDEV_VIRDEV ) &&
1228 : 0 : ( GetRefDevice()->GetOutDevType() == OUTDEV_VIRDEV ) ) )
1229 : 0 : bUsePortionInfo = sal_True;
1230 : : }
1231 : :
1232 : 132345 : sal_Bool bConvertItems = sal_False;
1233 : 132345 : MapUnit eSourceUnit = MapUnit(), eDestUnit = MapUnit();
1234 [ + - ]: 132345 : if ( rTextObject.HasMetric() )
1235 : : {
1236 : 132345 : eSourceUnit = (MapUnit)rTextObject.GetMetric();
1237 [ + - ]: 132345 : eDestUnit = (MapUnit)aEditDoc.GetItemPool().GetMetric( DEF_METRIC );
1238 [ - + ]: 132345 : if ( eSourceUnit != eDestUnit )
1239 : 0 : bConvertItems = sal_True;
1240 : : }
1241 : :
1242 [ + - ]: 132345 : size_t nContents = rTextObject.GetContents().size();
1243 [ + - ][ + - ]: 132345 : sal_uInt16 nPara = aEditDoc.GetPos( aPaM.GetNode() );
1244 : :
1245 [ + + ]: 274350 : for (size_t n = 0; n < nContents; ++n, ++nPara)
1246 : : {
1247 [ + - ][ + - ]: 142005 : ContentInfo* pC = &rTextObject.GetContents()[n];
1248 [ + - ][ + - ]: 142005 : sal_Bool bNewContent = aPaM.GetNode()->Len() ? sal_False: sal_True;
1249 : 142005 : sal_uInt16 nStartPos = aPaM.GetIndex();
1250 : :
1251 [ + - ][ + - ]: 142005 : aPaM = ImpFastInsertText( aPaM, pC->GetText() );
[ + - ]
1252 : :
1253 [ + - ][ + - ]: 142005 : ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
1254 : : DBG_ASSERT( pPortion, "Blind Portion in FastInsertText" );
1255 [ + - ]: 142005 : pPortion->MarkInvalid( nStartPos, pC->GetText().Len() );
1256 : :
1257 : : // Character attributes ...
1258 [ + - ][ + - ]: 142005 : sal_Bool bAllreadyHasAttribs = aPaM.GetNode()->GetCharAttribs().Count() ? sal_True : sal_False;
[ - + ]
1259 : 142005 : size_t nNewAttribs = pC->GetAttribs().size();
1260 [ + + ]: 142005 : if ( nNewAttribs )
1261 : : {
1262 : 6703 : sal_Bool bUpdateFields = sal_False;
1263 [ + + ]: 76191 : for (size_t nAttr = 0; nAttr < nNewAttribs; ++nAttr)
1264 : : {
1265 [ + - ]: 69488 : const XEditAttribute& rX = pC->GetAttribs()[nAttr];
1266 : : // Can happen when paragraphs > 16K, it is simply wrapped.
1267 [ + - ][ + - ]: 69488 : if ( rX.GetEnd() <= aPaM.GetNode()->Len() )
[ + - ]
1268 : : {
1269 [ - + ][ # # ]: 69488 : if ( !bAllreadyHasAttribs || rX.IsFeature() )
[ # # ][ + - ]
1270 : : {
1271 : : // Normal attributes then go faster ...
1272 : : // Features shall not be inserted through
1273 : : // EditDoc:: InsertAttrib, using FastInsertText they are
1274 : : // already in the flow
1275 : : DBG_ASSERT( rX.GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute too large!" );
1276 : : EditCharAttrib* pAttr;
1277 [ + - ]: 69488 : if ( !bConvertItems )
1278 [ + - ]: 69488 : pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos );
1279 : : else
1280 : : {
1281 [ # # ]: 0 : SfxPoolItem* pNew = rX.GetItem()->Clone();
1282 [ # # ]: 0 : ConvertItem( *pNew, eSourceUnit, eDestUnit );
1283 [ # # ]: 0 : pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos );
1284 [ # # ][ # # ]: 0 : delete pNew;
1285 : : }
1286 : : DBG_ASSERT( pAttr->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (1)" );
1287 [ + - ][ + - ]: 69488 : aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttr );
1288 [ + + ]: 69488 : if ( pAttr->Which() == EE_FEATURE_FIELD )
1289 : 3732 : bUpdateFields = sal_True;
1290 : : }
1291 : : else
1292 : : {
1293 : : DBG_ASSERT( rX.GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (2)" );
1294 : : // Tabs and other Features can not be inserted through InsertAttrib:
1295 [ # # ][ # # ]: 0 : aEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() );
1296 : : }
1297 : : }
1298 : : }
1299 [ + + ]: 6703 : if ( bUpdateFields )
1300 [ + - ]: 3642 : UpdateFields();
1301 : :
1302 : : // Otherwise, quick format => no attributes!
1303 [ + - ]: 6703 : pPortion->MarkSelectionInvalid( nStartPos, pC->GetText().Len() );
1304 : : }
1305 : :
1306 : : DBG_ASSERT( CheckOrderedList( aPaM.GetNode()->GetCharAttribs().GetAttribs(), sal_True ), "InsertBinTextObject: Start-Liste distorted" );
1307 : :
1308 : 142005 : sal_Bool bParaAttribs = sal_False;
1309 [ - + ][ # # ]: 142005 : if ( bNewContent || ( ( n > 0 ) && ( n < (nContents-1) ) ) )
[ # # ]
1310 : : {
1311 : 142005 : bParaAttribs = sal_False;
1312 : : {
1313 : : // only style and ParaAttribs when new paragraph, or
1314 : : // completely internal ...
1315 [ + + ]: 142005 : bParaAttribs = pC->GetParaAttribs().Count() ? sal_True : sal_False;
1316 [ + + ][ + + ]: 142005 : if ( GetStyleSheetPool() && pC->GetStyle().Len() )
[ + + ]
1317 : : {
1318 [ + - ]: 17095 : SfxStyleSheet* pStyle = (SfxStyleSheet*)GetStyleSheetPool()->Find( pC->GetStyle(), pC->GetFamily() );
1319 : : DBG_ASSERT( pStyle, "InsertBinTextObject - Style not found!" );
1320 [ + - ]: 17095 : SetStyleSheet( nPara, pStyle );
1321 : : }
1322 [ + - ]: 142005 : if ( !bConvertItems )
1323 [ + - ][ + - ]: 142005 : SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() );
[ + - ]
1324 : : else
1325 : : {
1326 [ # # ][ # # ]: 0 : SfxItemSet aAttribs( GetEmptyItemSet() );
1327 [ # # ]: 0 : ConvertAndPutItems( aAttribs, pC->GetParaAttribs(), &eSourceUnit, &eDestUnit );
1328 [ # # ][ # # ]: 0 : SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), aAttribs );
[ # # ][ # # ]
1329 : : }
1330 : : }
1331 [ + - ][ - + ]: 142005 : if ( bNewContent && bUsePortionInfo )
1332 : : {
1333 [ # # ]: 0 : const XParaPortion& rXP = (*pPortionInfo)[n];
1334 [ # # ]: 0 : ParaPortion* pParaPortion = GetParaPortions()[ nPara ];
1335 : : DBG_ASSERT( pParaPortion, "InsertBinTextObject: ParaPortion?" );
1336 : 0 : pParaPortion->nHeight = rXP.nHeight;
1337 : 0 : pParaPortion->nFirstLineOffset = rXP.nFirstLineOffset;
1338 : 0 : pParaPortion->bForceRepaint = sal_True;
1339 : 0 : pParaPortion->SetValid(); // Do not format
1340 : :
1341 : : // The Text Portions
1342 [ # # ]: 0 : pParaPortion->GetTextPortions().Reset();
1343 [ # # ]: 0 : sal_uInt16 nCount = rXP.aTextPortions.Count();
1344 [ # # ]: 0 : for ( sal_uInt16 _n = 0; _n < nCount; _n++ )
1345 : : {
1346 [ # # ]: 0 : const TextPortion* pTextPortion = rXP.aTextPortions[_n];
1347 [ # # ]: 0 : TextPortion* pNew = new TextPortion( *pTextPortion );
1348 [ # # ]: 0 : pParaPortion->GetTextPortions().Insert(_n, pNew);
1349 : : }
1350 : :
1351 : : // The lines
1352 [ # # ]: 0 : pParaPortion->GetLines().Reset();
1353 [ # # ]: 0 : nCount = rXP.aLines.Count();
1354 [ # # ]: 0 : for ( sal_uInt16 m = 0; m < nCount; m++ )
1355 : : {
1356 [ # # ]: 0 : const EditLine* pLine = rXP.aLines[m];
1357 [ # # ]: 0 : EditLine* pNew = pLine->Clone();
1358 : 0 : pNew->SetInvalid(); // Paint again!
1359 [ # # ]: 0 : pParaPortion->GetLines().Insert(m, pNew);
1360 : : }
1361 : : #ifdef DBG_UTIL
1362 : : sal_uInt16 nTest;
1363 : : int nTPLen = 0, nTxtLen = 0;
1364 : : for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; )
1365 : : nTPLen += pParaPortion->GetTextPortions()[--nTest]->GetLen();
1366 : : for ( nTest = pParaPortion->GetLines().Count(); nTest; )
1367 : : nTxtLen += pParaPortion->GetLines()[--nTest]->GetLen();
1368 : : DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "InsertBinTextObject: ParaPortion not completely formatted!" );
1369 : : #endif
1370 : : }
1371 : : }
1372 [ + + ]: 142005 : if ( !bParaAttribs ) // DefFont is not calculated for FastInsertParagraph
1373 : : {
1374 [ + - ][ + - ]: 4441 : aPaM.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
1375 [ + - ]: 4441 : if ( aStatus.UseCharAttribs() )
1376 [ + - ][ + - ]: 4441 : aPaM.GetNode()->CreateDefFont();
1377 : : }
1378 : :
1379 [ + - ][ + + ]: 142005 : if ( bNewContent && GetStatus().DoOnlineSpelling() && pC->GetWrongList() )
[ + + ][ + + ]
1380 : : {
1381 [ + - ][ + - ]: 11583 : aPaM.GetNode()->DestroyWrongList(); // otherwise MLK, if list exists...
1382 [ + - ][ + - ]: 11583 : aPaM.GetNode()->SetWrongList( pC->GetWrongList()->Clone() );
[ + - ]
1383 : : }
1384 : :
1385 : : // Wrap when followed by other ...
1386 [ + + ]: 142005 : if ( n < ( nContents-1) )
1387 : : {
1388 [ + - ]: 9660 : if ( bNewContent )
1389 [ + - ][ + - ]: 9660 : aPaM = ImpFastInsertParagraph( nPara+1 );
1390 : : else
1391 [ # # ][ # # ]: 0 : aPaM = ImpInsertParaBreak( aPaM, sal_False );
1392 : : }
1393 : : }
1394 : :
1395 [ + - ]: 132345 : aSel.Max() = aPaM;
1396 : : DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" );
1397 : 132345 : return aSel;
1398 : : }
1399 : :
1400 : 228959 : LanguageType ImpEditEngine::GetLanguage( const EditPaM& rPaM, sal_uInt16* pEndPos ) const
1401 : : {
1402 : 228959 : short nScriptType = GetScriptType( rPaM, pEndPos ); // pEndPos will be valid now, pointing to ScriptChange or NodeLen
1403 : 228959 : sal_uInt16 nLangId = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
1404 : 228959 : const SvxLanguageItem* pLangItem = &(const SvxLanguageItem&)rPaM.GetNode()->GetContentAttribs().GetItem( nLangId );
1405 : 228959 : const EditCharAttrib* pAttr = rPaM.GetNode()->GetCharAttribs().FindAttrib( nLangId, rPaM.GetIndex() );
1406 [ + + ]: 228959 : if ( pAttr )
1407 : 3753 : pLangItem = (const SvxLanguageItem*)pAttr->GetItem();
1408 : :
1409 [ - + ][ # # ]: 228959 : if ( pEndPos && pAttr && ( pAttr->GetEnd() < *pEndPos ) )
[ # # ][ - + ]
1410 : 0 : *pEndPos = pAttr->GetEnd();
1411 : :
1412 : 228959 : return pLangItem->GetLanguage();
1413 : : }
1414 : :
1415 : 225471 : ::com::sun::star::lang::Locale ImpEditEngine::GetLocale( const EditPaM& rPaM ) const
1416 : : {
1417 : 225471 : return SvxCreateLocale( GetLanguage( rPaM ) );
1418 : : }
1419 : :
1420 : 18 : Reference< XSpellChecker1 > ImpEditEngine::GetSpeller()
1421 : : {
1422 [ + - ]: 18 : if ( !xSpeller.is() )
1423 [ + - ]: 18 : xSpeller = SvxGetSpellChecker();
1424 : 18 : return xSpeller;
1425 : : }
1426 : :
1427 : :
1428 : 18 : SpellInfo * ImpEditEngine::CreateSpellInfo( bool bMultipleDocs )
1429 : : {
1430 [ + - ]: 18 : if (!pSpellInfo)
1431 [ + - ]: 18 : pSpellInfo = new SpellInfo;
1432 : : else
1433 [ # # ]: 0 : *pSpellInfo = SpellInfo(); // reset to default values
1434 : :
1435 : 18 : pSpellInfo->bMultipleDoc = bMultipleDocs;
1436 : : // always spell draw objects completely, startting at the top.
1437 : : // (spelling in only a selection or not starting with the top requires
1438 : : // further changes elsewehe to work properly)
1439 : 18 : pSpellInfo->aSpellStart = EPaM();
1440 : 18 : pSpellInfo->aSpellTo = EPaM( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND );
1441 : 18 : return pSpellInfo;
1442 : : }
1443 : :
1444 : :
1445 : 18 : EESpellState ImpEditEngine::Spell( EditView* pEditView, sal_Bool bMultipleDoc )
1446 : : {
1447 : : DBG_ASSERTWARNING( xSpeller.is(), "No Spell checker set!" );
1448 : :
1449 [ - + ]: 18 : if ( !xSpeller.is() )
1450 : 0 : return EE_SPELL_NOSPELLER;
1451 : :
1452 [ + - ]: 18 : aOnlineSpellTimer.Stop();
1453 : :
1454 : : // In MultipleDoc always from the front / rear ...
1455 [ - + ]: 18 : if ( bMultipleDoc )
1456 : : {
1457 [ # # ][ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
[ # # ]
1458 : : }
1459 : :
1460 [ + - ]: 18 : EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1461 [ + - ]: 18 : pSpellInfo = CreateSpellInfo( bMultipleDoc );
1462 : :
1463 : 18 : sal_Bool bIsStart = sal_False;
1464 [ - + ]: 18 : if ( bMultipleDoc )
1465 : 0 : bIsStart = sal_True; // Accessible from the front or from behind ...
1466 [ + - ][ + - ]: 18 : else if ( ( CreateEPaM( aEditDoc.GetStartPaM() ) == pSpellInfo->aSpellStart ) )
[ + - ]
1467 : 18 : bIsStart = sal_True;
1468 : :
1469 : : EditSpellWrapper* pWrp = new EditSpellWrapper( Application::GetDefDialogParent(),
1470 [ + - ][ + - ]: 18 : xSpeller, bIsStart, sal_False, pEditView );
[ + - ]
1471 [ + - ]: 18 : pWrp->SpellDocument();
1472 [ + - ][ + - ]: 18 : delete pWrp;
1473 : :
1474 [ + - ]: 18 : if ( !bMultipleDoc )
1475 : : {
1476 [ + - ]: 18 : pEditView->pImpEditView->DrawSelection();
1477 [ + - ][ + - ]: 18 : if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
[ - + ]
1478 [ # # ][ # # ]: 0 : aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
1479 [ + - ]: 18 : aCurSel.Min() = aCurSel.Max();
1480 [ + - ]: 18 : pEditView->pImpEditView->SetEditSelection( aCurSel );
1481 [ + - ]: 18 : pEditView->pImpEditView->DrawSelection();
1482 [ + - ]: 18 : pEditView->ShowCursor( sal_True, sal_False );
1483 : : }
1484 : 18 : EESpellState eState = pSpellInfo->eState;
1485 [ + - ]: 18 : delete pSpellInfo;
1486 : 18 : pSpellInfo = 0;
1487 : 18 : return eState;
1488 : : }
1489 : :
1490 : :
1491 : 0 : sal_Bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang )
1492 : : {
1493 : 0 : sal_Bool bHasConvTxt = sal_False;
1494 : :
1495 : 0 : sal_uInt16 nParas = pEditEngine->GetParagraphCount();
1496 [ # # ]: 0 : for (sal_uInt16 k = 0; k < nParas; ++k)
1497 : : {
1498 [ # # ]: 0 : std::vector<sal_uInt16> aPortions;
1499 [ # # ]: 0 : pEditEngine->GetPortions( k, aPortions );
1500 [ # # ]: 0 : for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos )
1501 : : {
1502 [ # # ]: 0 : sal_uInt16 nEnd = aPortions[ nPos ];
1503 [ # # ][ # # ]: 0 : sal_uInt16 nStart = nPos > 0 ? aPortions[ nPos - 1 ] : 0;
1504 : :
1505 : : // if the paragraph is not empty we need to increase the index
1506 : : // by one since the attribute of the character left to the
1507 : : // specified position is evaluated.
1508 [ # # ]: 0 : if (nEnd > nStart) // empty para?
1509 : 0 : ++nStart;
1510 [ # # ]: 0 : LanguageType nLangFound = pEditEngine->GetLanguage( k, nStart );
1511 : : #ifdef DEBUG
1512 : : lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
1513 : : #endif
1514 : : bHasConvTxt = (nSrcLang == nLangFound) ||
1515 [ # # ]: 0 : (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
1516 [ # # ][ # # ]: 0 : editeng::HangulHanjaConversion::IsChinese( nSrcLang ));
[ # # ][ # # ]
1517 [ # # ]: 0 : if (bHasConvTxt)
1518 : 0 : return bHasConvTxt;
1519 : : }
1520 [ # # ]: 0 : }
1521 : :
1522 : 0 : return bHasConvTxt;
1523 : : }
1524 : :
1525 : :
1526 : 0 : void ImpEditEngine::Convert( EditView* pEditView,
1527 : : LanguageType nSrcLang, LanguageType nDestLang, const Font *pDestFont,
1528 : : sal_Int32 nOptions, sal_Bool bIsInteractive, sal_Bool bMultipleDoc )
1529 : : {
1530 : : // modified version of ImpEditEngine::Spell
1531 : :
1532 : : // In MultipleDoc always from the front / rear ...
1533 [ # # ]: 0 : if ( bMultipleDoc )
1534 [ # # ][ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
[ # # ]
1535 : :
1536 : :
1537 : : // initialize pConvInfo
1538 [ # # ]: 0 : EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1539 [ # # ]: 0 : aCurSel.Adjust( aEditDoc );
1540 [ # # ]: 0 : pConvInfo = new ConvInfo;
1541 : 0 : pConvInfo->bMultipleDoc = bMultipleDoc;
1542 [ # # ]: 0 : pConvInfo->aConvStart = CreateEPaM( aCurSel.Min() );
1543 : : //
1544 : : // if it is not just a selection and we are about to begin
1545 : : // with the current conversion for the very first time
1546 : : // we need to find the start of the current (initial)
1547 : : // convertible unit in order for the text conversion to give
1548 : : // the correct result for that. Since it is easier to obtain
1549 : : // the start of the word we use that though.
1550 [ # # ][ # # ]: 0 : if (!aCurSel.HasRange() && ImplGetBreakIterator().is())
[ # # ][ # # ]
[ # # # # ]
[ # # ]
1551 : : {
1552 [ # # ][ # # ]: 0 : EditPaM aWordStartPaM( SelectWord( aCurSel, i18n::WordType::DICTIONARY_WORD ).Min() );
1553 : :
1554 : : // since #118246 / #117803 still occurs if the cursor is placed
1555 : : // between the two chinese characters to be converted (because both
1556 : : // of them are words on their own!) using the word boundary here does
1557 : : // not work. Thus since chinese conversion is not interactive we start
1558 : : // at the begin of the paragraph to solve the problem, i.e. have the
1559 : : // TextConversion service get those characters together in the same call.
1560 [ # # ]: 0 : sal_uInt16 nStartIdx = ( editeng::HangulHanjaConversion::IsChinese( nSrcLang ) ) ?
1561 [ # # ]: 0 : 0 : aWordStartPaM.GetIndex();
1562 : 0 : pConvInfo->aConvStart.nIndex = nStartIdx;
1563 : : }
1564 : : //
1565 : 0 : pConvInfo->aConvContinue = pConvInfo->aConvStart;
1566 : :
1567 : 0 : sal_Bool bIsStart = sal_False;
1568 [ # # ]: 0 : if ( bMultipleDoc )
1569 : 0 : bIsStart = sal_True; // Accessible from the front or from behind ...
1570 [ # # ][ # # ]: 0 : else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pConvInfo->aConvStart )
[ # # ]
1571 : 0 : bIsStart = sal_True;
1572 : :
1573 : 0 : bImpConvertFirstCall = true; // next ImpConvert call is the very first in this conversion turn
1574 : :
1575 [ # # ]: 0 : Reference< lang::XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
1576 : : TextConvWrapper aWrp( Application::GetDefDialogParent(), xMSF,
1577 : : SvxCreateLocale( nSrcLang ), SvxCreateLocale( nDestLang ),
1578 : : pDestFont,
1579 : : nOptions, bIsInteractive,
1580 [ # # ][ # # ]: 0 : bIsStart, pEditView );
[ # # ][ # # ]
1581 : :
1582 : : //
1583 : : //!! optimization does not work since when update mode is false
1584 : : //!! the object is 'lying' about it portions, paragraphs,
1585 : : //!! EndPaM... later on.
1586 : : //!! Should not be a great problem since text boxes or cells in
1587 : : //!! Calc usually have only a rather short text.
1588 : : //
1589 : : // disallow formatting, updating the view, ... while
1590 : : // non-interactively converting the document. (saves time)
1591 : : //if (!bIsInteractive)
1592 : : // SetUpdateMode( sal_False );
1593 : :
1594 [ # # ]: 0 : aWrp.Convert();
1595 : :
1596 : : //if (!bIsInteractive)
1597 : : //SetUpdateMode( sal_True, 0, sal_True );
1598 : :
1599 [ # # ]: 0 : if ( !bMultipleDoc )
1600 : : {
1601 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
1602 [ # # ][ # # ]: 0 : if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() )
[ # # ]
1603 [ # # ][ # # ]: 0 : aCurSel.Max().GetIndex() = aCurSel.Max().GetNode()->Len();
1604 [ # # ]: 0 : aCurSel.Min() = aCurSel.Max();
1605 [ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aCurSel );
1606 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
1607 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
1608 : : }
1609 : 0 : delete pConvInfo;
1610 [ # # ]: 0 : pConvInfo = 0;
1611 : 0 : }
1612 : :
1613 : :
1614 : 0 : void ImpEditEngine::SetLanguageAndFont(
1615 : : const ESelection &rESel,
1616 : : LanguageType nLang, sal_uInt16 nLangWhichId,
1617 : : const Font *pFont, sal_uInt16 nFontWhichId )
1618 : : {
1619 [ # # ]: 0 : ESelection aOldSel = pActiveView->GetSelection();
1620 [ # # ]: 0 : pActiveView->SetSelection( rESel );
1621 : :
1622 : : // set new language attribute
1623 [ # # ][ # # ]: 0 : SfxItemSet aNewSet( pActiveView->GetEmptyItemSet() );
1624 [ # # ][ # # ]: 0 : aNewSet.Put( SvxLanguageItem( nLang, nLangWhichId ) );
[ # # ]
1625 : :
1626 : : // new font to be set?
1627 : : DBG_ASSERT( pFont, "target font missing?" );
1628 [ # # ]: 0 : if (pFont)
1629 : : {
1630 : : // set new font attribute
1631 [ # # ][ # # ]: 0 : SvxFontItem aFontItem = (SvxFontItem&) aNewSet.Get( nFontWhichId );
1632 [ # # ][ # # ]: 0 : aFontItem.SetFamilyName( pFont->GetName());
1633 [ # # ]: 0 : aFontItem.SetFamily( pFont->GetFamily());
1634 [ # # ][ # # ]: 0 : aFontItem.SetStyleName( pFont->GetStyleName());
1635 [ # # ]: 0 : aFontItem.SetPitch( pFont->GetPitch());
1636 [ # # ]: 0 : aFontItem.SetCharSet( pFont->GetCharSet() );
1637 [ # # ][ # # ]: 0 : aNewSet.Put( aFontItem );
1638 : : }
1639 : :
1640 : : // apply new attributes
1641 [ # # ]: 0 : pActiveView->SetAttribs( aNewSet );
1642 : :
1643 [ # # ][ # # ]: 0 : pActiveView->SetSelection( aOldSel );
1644 : 0 : }
1645 : :
1646 : :
1647 : 0 : void ImpEditEngine::ImpConvert( rtl::OUString &rConvTxt, LanguageType &rConvTxtLang,
1648 : : EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange,
1649 : : sal_Bool bAllowImplicitChangesForNotConvertibleText,
1650 : : LanguageType nTargetLang, const Font *pTargetFont )
1651 : : {
1652 : : // modified version of ImpEditEngine::ImpSpell
1653 : :
1654 : : // looks for next convertible text portion to be passed on to the wrapper
1655 : :
1656 [ # # ]: 0 : String aRes;
1657 : 0 : LanguageType nResLang = LANGUAGE_NONE;
1658 : :
1659 [ # # ][ # # ]: 0 : /* ContentNode* pLastNode = */ aEditDoc.GetObject( aEditDoc.Count()-1 );
1660 : :
1661 [ # # ]: 0 : EditPaM aPos( CreateEditPaM( pConvInfo->aConvContinue ) );
1662 [ # # ]: 0 : EditSelection aCurSel = EditSelection( aPos, aPos );
1663 : :
1664 [ # # ]: 0 : String aWord;
1665 : :
1666 [ # # ]: 0 : while (!aRes.Len())
1667 : : {
1668 : : // empty paragraph found that needs to have language and font set?
1669 [ # # # # ]: 0 : if (bAllowImplicitChangesForNotConvertibleText &&
[ # # ]
1670 [ # # ][ # # ]: 0 : !pEditEngine->GetText( pConvInfo->aConvContinue.nPara ).Len())
[ # # ][ # # ]
1671 : : {
1672 : 0 : sal_uInt16 nPara = pConvInfo->aConvContinue.nPara;
1673 : 0 : ESelection aESel( nPara, 0, nPara, 0 );
1674 : : // see comment for below same function call
1675 : : SetLanguageAndFont( aESel,
1676 : : nTargetLang, EE_CHAR_LANGUAGE_CJK,
1677 [ # # ]: 0 : pTargetFont, EE_CHAR_FONTINFO_CJK );
1678 : : }
1679 : :
1680 : :
1681 [ # # ][ # # ]: 0 : if (pConvInfo->aConvContinue.nPara == pConvInfo->aConvTo.nPara &&
1682 : : pConvInfo->aConvContinue.nIndex >= pConvInfo->aConvTo.nIndex)
1683 : : break;
1684 : :
1685 : 0 : sal_uInt16 nAttribStart = USHRT_MAX;
1686 : 0 : sal_uInt16 nAttribEnd = USHRT_MAX;
1687 : 0 : sal_uInt16 nCurPos = USHRT_MAX;
1688 [ # # ]: 0 : EPaM aCurStart = CreateEPaM( aCurSel.Min() );
1689 [ # # ]: 0 : std::vector<sal_uInt16> aPortions;
1690 [ # # ]: 0 : pEditEngine->GetPortions( (sal_uInt16)aCurStart.nPara, aPortions );
1691 [ # # ]: 0 : for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos )
1692 : : {
1693 [ # # ]: 0 : sal_uInt16 nEnd = aPortions[ nPos ];
1694 [ # # ][ # # ]: 0 : sal_uInt16 nStart = nPos > 0 ? aPortions[ nPos - 1 ] : 0;
1695 : :
1696 : : // the language attribute is obtained from the left character
1697 : : // (like usually all other attributes)
1698 : : // thus we usually have to add 1 in order to get the language
1699 : : // of the text right to the cursor position
1700 [ # # ]: 0 : sal_uInt16 nLangIdx = nEnd > nStart ? nStart + 1 : nStart;
1701 [ # # ]: 0 : LanguageType nLangFound = pEditEngine->GetLanguage( aCurStart.nPara, nLangIdx );
1702 : : #ifdef DEBUG
1703 : : lang::Locale aLocale( SvxCreateLocale( nLangFound ) );
1704 : : #endif
1705 : : sal_Bool bLangOk = (nLangFound == nSrcLang) ||
1706 [ # # ]: 0 : (editeng::HangulHanjaConversion::IsChinese( nLangFound ) &&
1707 [ # # ][ # # ]: 0 : editeng::HangulHanjaConversion::IsChinese( nSrcLang ));
[ # # ][ # # ]
1708 : :
1709 [ # # ]: 0 : if (nAttribEnd != USHRT_MAX) // start already found?
1710 : : {
1711 : : DBG_ASSERT(nEnd >= aCurStart.nIndex, "error while scanning attributes (a)" );
1712 : : DBG_ASSERT(nEnd >= nAttribEnd, "error while scanning attributes (b)" );
1713 [ # # ]: 0 : if (/*nEnd >= aCurStart.nIndex &&*/ nLangFound == nResLang)
1714 : 0 : nAttribEnd = nEnd;
1715 : : else // language attrib has changed
1716 : : break;
1717 : : }
1718 [ # # ][ # # ]: 0 : if (nAttribStart == USHRT_MAX && // start not yet found?
[ # # ]
1719 : : nEnd > aCurStart.nIndex && bLangOk)
1720 : : {
1721 : 0 : nAttribStart = nStart;
1722 : 0 : nAttribEnd = nEnd;
1723 : 0 : nResLang = nLangFound;
1724 : : }
1725 : : //! the list of portions may have changed compared to the previous
1726 : : //! call to this function (because of possibly changed language
1727 : : //! attribute!)
1728 : : //! But since we don't want to start in the already processed part
1729 : : //! we clip the start accordingly.
1730 [ # # ]: 0 : if (nAttribStart < aCurStart.nIndex)
1731 : : {
1732 : 0 : nAttribStart = aCurStart.nIndex;
1733 : : }
1734 : :
1735 : : // check script type to the right of the start of the current portion
1736 [ # # ]: 0 : EditPaM aPaM( CreateEditPaM( EPaM(aCurStart.nPara, nLangIdx) ) );
1737 [ # # ]: 0 : sal_Bool bIsAsianScript = (i18n::ScriptType::ASIAN == GetScriptType( aPaM ));
1738 : : // not yet processed text part with for conversion
1739 : : // not suitable language found that needs to be changed?
1740 [ # # ][ # # ]: 0 : if (bAllowImplicitChangesForNotConvertibleText &&
[ # # ][ # # ]
1741 : : !bLangOk && !bIsAsianScript && nEnd > aCurStart.nIndex)
1742 : : {
1743 : 0 : ESelection aESel( aCurStart.nPara, nStart, aCurStart.nPara, nEnd );
1744 : : // set language and font to target language and font of conversion
1745 : : //! Now this especially includes all non convertible text e.g.
1746 : : //! spaces, empty paragraphs and western text.
1747 : : // This is in order for every *new* text entered at *any* position to
1748 : : // have the correct language and font attributes set.
1749 : : SetLanguageAndFont( aESel,
1750 : : nTargetLang, EE_CHAR_LANGUAGE_CJK,
1751 [ # # ]: 0 : pTargetFont, EE_CHAR_FONTINFO_CJK );
1752 : : }
1753 : :
1754 : 0 : nCurPos = nEnd;
1755 : : }
1756 : :
1757 [ # # ][ # # ]: 0 : if (nAttribStart != USHRT_MAX && nAttribEnd != USHRT_MAX)
1758 : : {
1759 : 0 : aCurSel.Min().SetIndex( nAttribStart );
1760 : 0 : aCurSel.Max().SetIndex( nAttribEnd );
1761 : : }
1762 [ # # ]: 0 : else if (nCurPos != USHRT_MAX)
1763 : : {
1764 : : // set selection to end of scanned text
1765 : : // (used to set the position where to continue from later on)
1766 : 0 : aCurSel.Min().SetIndex( nCurPos );
1767 : 0 : aCurSel.Max().SetIndex( nCurPos );
1768 : : }
1769 : :
1770 [ # # ]: 0 : if ( !pConvInfo->bConvToEnd )
1771 : : {
1772 [ # # ]: 0 : EPaM aEPaM( CreateEPaM( aCurSel.Min() ) );
1773 [ # # ]: 0 : if ( !( aEPaM < pConvInfo->aConvTo ) )
1774 : : break;
1775 : : }
1776 : :
1777 : : // clip selected word to the converted area
1778 : : // (main use when conversion starts/ends **within** a word)
1779 [ # # ]: 0 : EditPaM aPaM( CreateEditPaM( pConvInfo->aConvStart ) );
1780 [ # # ]: 0 : if (pConvInfo->bConvToEnd &&
[ # # # # ]
[ # # ]
1781 [ # # ][ # # ]: 0 : aCurSel.Min().GetNode() == aPaM.GetNode() &&
1782 : 0 : aCurSel.Min().GetIndex() < aPaM.GetIndex())
1783 : 0 : aCurSel.Min().SetIndex( aPaM.GetIndex() );
1784 [ # # ][ # # ]: 0 : aPaM = CreateEditPaM( pConvInfo->aConvContinue );
1785 [ # # ][ # # ]: 0 : if (aCurSel.Min().GetNode() == aPaM.GetNode() &&
[ # # # # ]
[ # # ]
1786 : 0 : aCurSel.Min().GetIndex() < aPaM.GetIndex())
1787 : 0 : aCurSel.Min().SetIndex( aPaM.GetIndex() );
1788 [ # # ][ # # ]: 0 : aPaM = CreateEditPaM( pConvInfo->aConvTo );
1789 [ # # ][ # # ]: 0 : if ((!pConvInfo->bConvToEnd || rConvRange.HasRange())&&
[ # # # # ]
[ # # ]
1790 [ # # ][ # # ]: 0 : aCurSel.Max().GetNode() == aPaM.GetNode() &&
1791 : 0 : aCurSel.Max().GetIndex() > aPaM.GetIndex())
1792 : 0 : aCurSel.Max().SetIndex( aPaM.GetIndex() );
1793 : :
1794 [ # # ][ # # ]: 0 : aWord = GetSelected( aCurSel );
[ # # ]
1795 : :
1796 [ # # ]: 0 : if ( aWord.Len() > 0 /* && bLangOk */)
1797 [ # # ]: 0 : aRes = aWord;
1798 : :
1799 : : // move to next word/paragraph if necessary
1800 [ # # ]: 0 : if ( !aRes.Len() )
1801 [ # # ][ # # ]: 0 : aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1802 : :
1803 [ # # ][ # # ]: 0 : pConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() );
1804 : 0 : }
1805 : :
1806 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
1807 [ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aCurSel );
1808 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
1809 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
1810 : :
1811 [ # # ]: 0 : rConvTxt = aRes;
1812 [ # # ]: 0 : if ( !rConvTxt.isEmpty() )
1813 [ # # ][ # # ]: 0 : rConvTxtLang = nResLang;
1814 : 0 : }
1815 : :
1816 : :
1817 : 18 : Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView )
1818 : : {
1819 : : DBG_ASSERT( xSpeller.is(), "No spell checker set!" );
1820 : :
1821 [ + - ][ + - ]: 18 : ContentNode* pLastNode = aEditDoc.GetObject( (aEditDoc.Count()-1) );
1822 [ + - ]: 18 : EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
1823 [ + - ]: 18 : aCurSel.Min() = aCurSel.Max();
1824 : :
1825 [ + - ]: 18 : String aWord;
1826 : 18 : Reference< XSpellAlternatives > xSpellAlt;
1827 [ + - ]: 18 : Sequence< PropertyValue > aEmptySeq;
1828 [ + - ]: 18 : while (!xSpellAlt.is())
1829 : : {
1830 : : // Known (most likely) bug: If SpellToCurrent, the current has to be
1831 : : // corrected at each replacement, otherwise it may not fit exactly in
1832 : : // the end ...
1833 [ + - ][ - + ]: 18 : if ( pSpellInfo->bSpellToEnd || pSpellInfo->bMultipleDoc )
1834 : : {
1835 [ # # ][ # # ]: 0 : if ( aCurSel.Max().GetNode() == pLastNode )
1836 : : {
1837 [ # # ][ # # ]: 0 : if ( ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
1838 : 0 : break;
1839 : : }
1840 : : }
1841 [ + - ]: 18 : else if ( !pSpellInfo->bSpellToEnd )
1842 : : {
1843 [ + - ]: 18 : EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
1844 [ - + ]: 18 : if ( !( aEPaM < pSpellInfo->aSpellTo ) )
1845 : : break;
1846 : : }
1847 : :
1848 [ # # ][ # # ]: 0 : aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1849 [ # # ][ # # ]: 0 : aWord = GetSelected( aCurSel );
[ # # ]
1850 : :
1851 : : // If afterwards a dot, this must be handed over!
1852 : : // If an abbreviation ...
1853 [ # # ][ # # ]: 0 : if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
[ # # ][ # # ]
[ # # ]
1854 : : {
1855 [ # # ][ # # ]: 0 : sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
1856 [ # # ]: 0 : if ( cNext == '.' )
1857 : : {
1858 : 0 : aCurSel.Max().GetIndex()++;
1859 [ # # ]: 0 : aWord += cNext;
1860 : : }
1861 : : }
1862 : :
1863 [ # # ]: 0 : if ( aWord.Len() > 0 )
1864 : : {
1865 [ # # ]: 0 : LanguageType eLang = GetLanguage( aCurSel.Max() );
1866 [ # # ]: 0 : SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
1867 [ # # ][ # # ]: 0 : xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
[ # # ][ # # ]
1868 : : }
1869 : :
1870 [ # # ]: 0 : if ( !xSpellAlt.is() )
1871 [ # # ][ # # ]: 0 : aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1872 : : else
1873 : 0 : pSpellInfo->eState = EE_SPELL_ERRORFOUND;
1874 : : }
1875 : :
1876 [ + - ]: 18 : pEditView->pImpEditView->DrawSelection();
1877 [ + - ]: 18 : pEditView->pImpEditView->SetEditSelection( aCurSel );
1878 [ + - ]: 18 : pEditView->pImpEditView->DrawSelection();
1879 [ + - ]: 18 : pEditView->ShowCursor( sal_True, sal_False );
1880 [ + - ][ + - ]: 18 : return xSpellAlt;
1881 : : }
1882 : :
1883 : 0 : void ImpEditEngine::StartSpelling(EditView& rEditView, sal_Bool bMultipleDoc)
1884 : : {
1885 : : DBG_ASSERT(!pSpellInfo, "pSpellInfo already set?");
1886 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() );
1887 : 0 : pSpellInfo = CreateSpellInfo( bMultipleDoc );
1888 : 0 : }
1889 : :
1890 : 0 : Reference< XSpellAlternatives > ImpEditEngine::ImpFindNextError(EditSelection& rSelection)
1891 : : {
1892 [ # # ][ # # ]: 0 : aEditDoc.GetObject( (aEditDoc.Count()-1) );
1893 [ # # ]: 0 : EditSelection aCurSel( rSelection.Min() );
1894 : :
1895 [ # # ]: 0 : String aWord;
1896 : 0 : Reference< XSpellAlternatives > xSpellAlt;
1897 [ # # ]: 0 : Sequence< PropertyValue > aEmptySeq;
1898 [ # # ]: 0 : while (!xSpellAlt.is())
1899 : : {
1900 : : //check if the end of the selection has been reached
1901 : : {
1902 [ # # ]: 0 : EPaM aEPaM( CreateEPaM( aCurSel.Max() ) );
1903 [ # # ][ # # ]: 0 : if ( !( aEPaM < CreateEPaM( rSelection.Max()) ) )
1904 : : break;
1905 : : }
1906 : :
1907 [ # # ][ # # ]: 0 : aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1908 [ # # ][ # # ]: 0 : aWord = GetSelected( aCurSel );
[ # # ]
1909 : :
1910 : : // If afterwards a dot, this must be handed over!
1911 : : // If an abbreviation ...
1912 [ # # ][ # # ]: 0 : if ( aWord.Len() && ( aCurSel.Max().GetIndex() < aCurSel.Max().GetNode()->Len() ) )
[ # # ][ # # ]
[ # # ]
1913 : : {
1914 [ # # ][ # # ]: 0 : sal_Unicode cNext = aCurSel.Max().GetNode()->GetChar( aCurSel.Max().GetIndex() );
1915 [ # # ]: 0 : if ( cNext == '.' )
1916 : : {
1917 : 0 : aCurSel.Max().GetIndex()++;
1918 [ # # ]: 0 : aWord += cNext;
1919 : : }
1920 : : }
1921 : :
1922 [ # # ]: 0 : if ( aWord.Len() > 0 )
1923 [ # # ][ # # ]: 0 : xSpellAlt = xSpeller->spell( aWord, GetLanguage( aCurSel.Max() ), aEmptySeq );
[ # # ][ # # ]
[ # # ]
1924 : :
1925 [ # # ]: 0 : if ( !xSpellAlt.is() )
1926 [ # # ][ # # ]: 0 : aCurSel = WordRight( aCurSel.Min(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
1927 : : else
1928 : : {
1929 : 0 : pSpellInfo->eState = EE_SPELL_ERRORFOUND;
1930 [ # # ]: 0 : rSelection = aCurSel;
1931 : : }
1932 : : }
1933 [ # # ][ # # ]: 0 : return xSpellAlt;
1934 : : }
1935 : :
1936 : 0 : bool ImpEditEngine::SpellSentence(EditView& rEditView,
1937 : : ::svx::SpellPortions& rToFill,
1938 : : bool /*bIsGrammarChecking*/ )
1939 : : {
1940 : 0 : bool bRet = false;
1941 [ # # ]: 0 : EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() );
1942 [ # # ]: 0 : if(!pSpellInfo)
1943 [ # # ]: 0 : pSpellInfo = CreateSpellInfo( true );
1944 [ # # ]: 0 : pSpellInfo->aCurSentenceStart = aCurSel.Min();
1945 : : DBG_ASSERT( xSpeller.is(), "No spell checker set!" );
1946 : 0 : pSpellInfo->aLastSpellPortions.clear();
1947 : 0 : pSpellInfo->aLastSpellContentSelections.clear();
1948 : 0 : rToFill.clear();
1949 : : //if no selection previously exists the range is extended to the end of the object
1950 [ # # ][ # # ]: 0 : if(aCurSel.Min() == aCurSel.Max())
1951 : : {
1952 [ # # ][ # # ]: 0 : ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1);
1953 [ # # ][ # # ]: 0 : aCurSel.Max() = EditPaM(pLastNode, pLastNode->Len());
[ # # ]
1954 : : }
1955 : : // check for next error in aCurSel and set aCurSel to that one if any was found
1956 [ # # ]: 0 : Reference< XSpellAlternatives > xAlt = ImpFindNextError(aCurSel);
1957 [ # # ]: 0 : if (xAlt.is())
1958 : : {
1959 : 0 : bRet = true;
1960 : : //find the sentence boundaries
1961 [ # # ]: 0 : EditSelection aSentencePaM = SelectSentence(aCurSel);
1962 : : //make sure that the sentence is never smaller than the error range!
1963 [ # # ]: 0 : if(aSentencePaM.Max().GetIndex() < aCurSel.Max().GetIndex())
1964 [ # # ]: 0 : aSentencePaM.Max() = aCurSel.Max();
1965 : : //add the portion preceeding the error
1966 [ # # ]: 0 : EditSelection aStartSelection(aSentencePaM.Min(), aCurSel.Min());
1967 [ # # ][ # # ]: 0 : if(aStartSelection.HasRange())
1968 [ # # ][ # # ]: 0 : AddPortionIterated(rEditView, aStartSelection, 0, rToFill);
1969 : : //add the error portion
1970 [ # # ]: 0 : AddPortionIterated(rEditView, aCurSel, xAlt, rToFill);
1971 : : //find the end of the sentence
1972 : : //search for all errors in the rest of the sentence and add all the portions
1973 [ # # ]: 0 : do
1974 : : {
1975 [ # # ]: 0 : EditSelection aNextSel = EditSelection(aCurSel.Max(), aSentencePaM.Max());
1976 [ # # ][ # # ]: 0 : xAlt = ImpFindNextError(aNextSel);
1977 [ # # ]: 0 : if(xAlt.is())
1978 : : {
1979 : : //add the part between the previous and the current error
1980 [ # # ][ # # ]: 0 : AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aNextSel.Min()), 0, rToFill);
[ # # ]
1981 : : //add the current error
1982 [ # # ]: 0 : AddPortionIterated(rEditView, aNextSel, xAlt, rToFill);
1983 : : }
1984 : : else
1985 [ # # ][ # # ]: 0 : AddPortionIterated(rEditView, EditSelection(aCurSel.Max(), aSentencePaM.Max()), xAlt, rToFill);
1986 [ # # ]: 0 : aCurSel = aNextSel;
1987 : : }
1988 : 0 : while( xAlt.is() );
1989 : :
1990 : : //set the selection to the end of the current sentence
1991 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection(aSentencePaM.Max());
1992 : : }
1993 : 0 : return bRet;
1994 : : }
1995 : :
1996 : : // Adds one portion to the SpellPortions
1997 : 0 : void ImpEditEngine::AddPortion(
1998 : : const EditSelection& rSel,
1999 : : uno::Reference< XSpellAlternatives > xAlt,
2000 : : ::svx::SpellPortions& rToFill,
2001 : : bool bIsField)
2002 : : {
2003 [ # # ]: 0 : if(rSel.HasRange())
2004 : : {
2005 [ # # ]: 0 : svx::SpellPortion aPortion;
2006 [ # # ][ # # ]: 0 : aPortion.sText = GetSelected( rSel );
[ # # ]
2007 [ # # ]: 0 : aPortion.eLanguage = GetLanguage( rSel.Min() );
2008 [ # # ]: 0 : aPortion.xAlternatives = xAlt;
2009 : 0 : aPortion.bIsField = bIsField;
2010 [ # # ]: 0 : rToFill.push_back(aPortion);
2011 : :
2012 : : //save the spelled portions for later use
2013 [ # # ]: 0 : pSpellInfo->aLastSpellPortions.push_back(aPortion);
2014 [ # # ][ # # ]: 0 : pSpellInfo->aLastSpellContentSelections.push_back(rSel);
2015 : :
2016 : : }
2017 : 0 : }
2018 : :
2019 : : // Adds one or more portions of text to the SpellPortions depending on language changes
2020 : 0 : void ImpEditEngine::AddPortionIterated(
2021 : : EditView& rEditView,
2022 : : const EditSelection& rSel,
2023 : : Reference< XSpellAlternatives > xAlt,
2024 : : ::svx::SpellPortions& rToFill)
2025 : : {
2026 [ # # ]: 0 : if(rSel.Min() != rSel.Max())
2027 : : {
2028 [ # # ]: 0 : if(xAlt.is())
2029 : : {
2030 [ # # ]: 0 : AddPortion(rSel, xAlt, rToFill, false);
2031 : : }
2032 : : else
2033 : : {
2034 : : //iterate and search for language attribute changes
2035 : : //save the start and end positions
2036 : 0 : bool bTest = rSel.Min().GetIndex() <= rSel.Max().GetIndex();
2037 [ # # ][ # # ]: 0 : EditPaM aStart(bTest ? rSel.Min() : rSel.Max());
2038 [ # # ][ # # ]: 0 : EditPaM aEnd(bTest ? rSel.Max() : rSel.Min());
2039 : : //iterate over the text to find changes in language
2040 : : //set the mark equal to the point
2041 [ # # ]: 0 : EditPaM aCursor(aStart);
2042 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection( aCursor );
2043 [ # # ]: 0 : LanguageType eStartLanguage = GetLanguage( aCursor );
2044 : : //search for a field attribute at the beginning - only the end position
2045 : : //of this field is kept to end a portion at that position
2046 [ # # ]: 0 : const EditCharAttrib* pFieldAttr = aCursor.GetNode()->GetCharAttribs().
2047 [ # # ]: 0 : FindFeature( aCursor.GetIndex() );
2048 : : bool bIsField = pFieldAttr &&
2049 : 0 : pFieldAttr->GetStart() == aCursor.GetIndex() &&
2050 : 0 : pFieldAttr->GetStart() != pFieldAttr->GetEnd() &&
2051 [ # # # # : 0 : pFieldAttr->Which() == EE_FEATURE_FIELD;
# # ][ # # ]
2052 [ # # ]: 0 : sal_uInt16 nEndField = bIsField ? pFieldAttr->GetEnd() : USHRT_MAX;
2053 : 0 : bool bIsEndField = false;
2054 [ # # ]: 0 : do
2055 : : {
2056 [ # # ][ # # ]: 0 : aCursor = CursorRight( aCursor);
2057 : : //determine whether a field and has been reached
2058 : 0 : bIsEndField = nEndField == aCursor.GetIndex();
2059 : : //search for a new field attribute
2060 [ # # ]: 0 : const EditCharAttrib* _pFieldAttr = aCursor.GetNode()->GetCharAttribs().
2061 [ # # ]: 0 : FindFeature( aCursor.GetIndex() );
2062 : : bIsField = _pFieldAttr &&
2063 : 0 : _pFieldAttr->GetStart() == aCursor.GetIndex() &&
2064 : 0 : _pFieldAttr->GetStart() != _pFieldAttr->GetEnd() &&
2065 [ # # # # : 0 : _pFieldAttr->Which() == EE_FEATURE_FIELD;
# # ][ # # ]
2066 : : //on every new field move the end position
2067 [ # # ]: 0 : if(bIsField)
2068 [ # # ]: 0 : nEndField = bIsField ? _pFieldAttr->GetEnd() : USHRT_MAX;
2069 : :
2070 [ # # ]: 0 : LanguageType eCurLanguage = GetLanguage( aCursor );
2071 [ # # ][ # # ]: 0 : if(eCurLanguage != eStartLanguage || bIsField || bIsEndField)
[ # # ]
2072 : : {
2073 : 0 : eStartLanguage = eCurLanguage;
2074 : : //go one step back - the cursor currently selects the first character
2075 : : //with a different language
2076 : : //create a selection from start to the current Cursor
2077 [ # # ]: 0 : EditSelection aSelection(aStart, aCursor);
2078 [ # # ]: 0 : AddPortion(aSelection, xAlt, rToFill, bIsEndField);
2079 [ # # ]: 0 : aStart = aCursor;
2080 : : }
2081 : : }
2082 : 0 : while(aCursor.GetIndex() < aEnd.GetIndex());
2083 [ # # ]: 0 : EditSelection aSelection(aStart, aCursor);
2084 [ # # ]: 0 : AddPortion(aSelection, xAlt, rToFill, bIsField);
2085 : : }
2086 : : }
2087 : 0 : }
2088 : :
2089 : 0 : void ImpEditEngine::ApplyChangedSentence(EditView& rEditView,
2090 : : const ::svx::SpellPortions& rNewPortions,
2091 : : bool bRecheck )
2092 : : {
2093 : : // Note: rNewPortions.size() == 0 is valid and happens when the whole
2094 : : // sentence got removed in the dialog
2095 : :
2096 : : DBG_ASSERT(pSpellInfo, "pSpellInfo not initialized");
2097 [ # # # # ]: 0 : if (pSpellInfo &&
[ # # ]
2098 : 0 : pSpellInfo->aLastSpellPortions.size() > 0) // no portions -> no text to be changed
2099 : : {
2100 : : // get current paragraph length to calculate later on how the sentence length changed,
2101 : : // in order to place the cursor at the end of the sentence again
2102 [ # # ]: 0 : EditSelection aOldSel( rEditView.pImpEditView->GetEditSelection() );
2103 [ # # ][ # # ]: 0 : xub_StrLen nOldLen = aOldSel.Max().GetNode()->Len();
2104 : :
2105 [ # # ]: 0 : UndoActionStart( EDITUNDO_INSERT );
2106 [ # # ]: 0 : if(pSpellInfo->aLastSpellPortions.size() == rNewPortions.size())
2107 : : {
2108 : : DBG_ASSERT( rNewPortions.size() > 0, "rNewPortions should not be empty here" );
2109 : : DBG_ASSERT( pSpellInfo->aLastSpellPortions.size() == pSpellInfo->aLastSpellContentSelections.size(),
2110 : : "aLastSpellPortions and aLastSpellContentSelections size mismatch" );
2111 : :
2112 : : //the simple case: the same number of elements on both sides
2113 : : //each changed element has to be applied to the corresponding source element
2114 : 0 : svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
2115 [ # # ]: 0 : svx::SpellPortions::const_iterator aCurrentOldPortion = pSpellInfo->aLastSpellPortions.end();
2116 [ # # ]: 0 : SpellContentSelections::const_iterator aCurrentOldPosition = pSpellInfo->aLastSpellContentSelections.end();
2117 : 0 : bool bSetToEnd = false;
2118 [ # # ][ # # ]: 0 : do
2119 : : {
2120 : 0 : --aCurrentNewPortion;
2121 : 0 : --aCurrentOldPortion;
2122 : 0 : --aCurrentOldPosition;
2123 : : //set the cursor to the end of the sentence - necessary to
2124 : : //resume there at the next step
2125 [ # # ]: 0 : if(!bSetToEnd)
2126 : : {
2127 : 0 : bSetToEnd = true;
2128 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection( aCurrentOldPosition->Max() );
2129 : : }
2130 : :
2131 [ # # ]: 0 : sal_uInt16 nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
2132 : 0 : sal_uInt16 nLangWhichId = EE_CHAR_LANGUAGE;
2133 [ # # # ]: 0 : switch(nScriptType)
2134 : : {
2135 : 0 : case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
2136 : 0 : case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
2137 : : }
2138 [ # # ]: 0 : if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
2139 : : {
2140 : : //change text and apply language
2141 [ # # ]: 0 : SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2142 [ # # ][ # # ]: 0 : aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
[ # # ]
2143 [ # # ][ # # ]: 0 : SetAttribs( *aCurrentOldPosition, aSet );
2144 [ # # ][ # # ]: 0 : ImpInsertText( *aCurrentOldPosition, aCurrentNewPortion->sText );
[ # # ][ # # ]
2145 : : }
2146 [ # # ]: 0 : else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
2147 : : {
2148 : : //apply language
2149 [ # # ]: 0 : SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2150 [ # # ][ # # ]: 0 : aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
[ # # ]
2151 [ # # ][ # # ]: 0 : SetAttribs( *aCurrentOldPosition, aSet );
[ # # ]
2152 : : }
2153 [ # # ][ # # ]: 0 : if(aCurrentNewPortion == rNewPortions.begin())
2154 : 0 : break;
2155 : : }
2156 : 0 : while(aCurrentNewPortion != rNewPortions.begin());
2157 : : }
2158 : : else
2159 : : {
2160 : : DBG_ASSERT( !pSpellInfo->aLastSpellContentSelections.empty(), "aLastSpellContentSelections should not be empty here" );
2161 : :
2162 : : //select the complete sentence
2163 [ # # ]: 0 : SpellContentSelections::const_iterator aCurrentEndPosition = pSpellInfo->aLastSpellContentSelections.end();
2164 : 0 : --aCurrentEndPosition;
2165 [ # # ]: 0 : SpellContentSelections::const_iterator aCurrentStartPosition = pSpellInfo->aLastSpellContentSelections.begin();
2166 [ # # ]: 0 : EditSelection aAllSentence(aCurrentStartPosition->Min(), aCurrentEndPosition->Max());
2167 : :
2168 : : //delete the sentence completely
2169 [ # # ]: 0 : ImpDeleteSelection( aAllSentence );
2170 : 0 : svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.begin();
2171 [ # # ]: 0 : EditPaM aCurrentPaM = aAllSentence.Min();
2172 [ # # ][ # # ]: 0 : while(aCurrentNewPortion != rNewPortions.end())
2173 : : {
2174 : : //set the language attribute
2175 [ # # ]: 0 : LanguageType eCurLanguage = GetLanguage( aCurrentPaM );
2176 [ # # ]: 0 : if(eCurLanguage != aCurrentNewPortion->eLanguage)
2177 : : {
2178 [ # # ]: 0 : sal_uInt16 nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
2179 : 0 : sal_uInt16 nLangWhichId = EE_CHAR_LANGUAGE;
2180 [ # # # ]: 0 : switch(nScriptType)
2181 : : {
2182 : 0 : case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
2183 : 0 : case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
2184 : : }
2185 [ # # ]: 0 : SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId);
2186 [ # # ][ # # ]: 0 : aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId));
[ # # ]
2187 [ # # ][ # # ]: 0 : SetAttribs( aCurrentPaM, aSet );
[ # # ]
2188 : : }
2189 : : //insert the new string and set the cursor to the end of the inserted string
2190 [ # # ][ # # ]: 0 : aCurrentPaM = ImpInsertText( aCurrentPaM , aCurrentNewPortion->sText );
[ # # ][ # # ]
[ # # ]
2191 : 0 : ++aCurrentNewPortion;
2192 : : }
2193 : : }
2194 [ # # ]: 0 : UndoActionEnd( EDITUNDO_INSERT );
2195 : :
2196 [ # # ]: 0 : EditPaM aNext;
2197 [ # # ]: 0 : if (bRecheck)
2198 [ # # ]: 0 : aNext = pSpellInfo->aCurSentenceStart;
2199 : : else
2200 : : {
2201 : : // restore cursor position to the end of the modified sentence.
2202 : : // (This will define the continuation position for spell/grammar checking)
2203 : : // First: check if the sentence/para length changed
2204 [ # # ][ # # ]: 0 : sal_Int32 nDelta = rEditView.pImpEditView->GetEditSelection().Max().GetNode()->Len() - nOldLen;
2205 : 0 : xub_StrLen nEndOfSentence = aOldSel.Max().GetIndex() + nDelta;
2206 [ # # ][ # # ]: 0 : aNext = EditPaM( aOldSel.Max().GetNode(), nEndOfSentence );
[ # # ]
2207 : : }
2208 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection( aNext );
2209 : :
2210 [ # # ]: 0 : FormatAndUpdate();
2211 [ # # ]: 0 : aEditDoc.SetModified(sal_True);
2212 : : }
2213 : 0 : }
2214 : :
2215 : 0 : void ImpEditEngine::PutSpellingToSentenceStart( EditView& rEditView )
2216 : : {
2217 [ # # ][ # # ]: 0 : if( pSpellInfo && !pSpellInfo->aLastSpellContentSelections.empty() )
[ # # ]
2218 : : {
2219 [ # # ][ # # ]: 0 : rEditView.pImpEditView->SetEditSelection( pSpellInfo->aLastSpellContentSelections.begin()->Min() );
2220 : : }
2221 : 0 : }
2222 : :
2223 : :
2224 : 3009 : void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, sal_Bool bSpellAtCursorPos, sal_Bool bInteruptable )
2225 : : {
2226 : : /*
2227 : : It will iterate over all the paragraphs, paragraphs with only
2228 : : invalidated wrong list will be checked ...
2229 : :
2230 : : All the words are checked in the invalidated region. Is a word wrong,
2231 : : but not in the wrong list, or vice versa, the range of the word will be
2232 : : invalidated
2233 : : (no Invalidate, but if only transitions wrong from right =>, simple Paint,
2234 : : even out properly with VDev on transitions from wrong => right)
2235 : : */
2236 : :
2237 [ + + ]: 3009 : if ( !xSpeller.is() )
2238 : 3009 : return;
2239 : :
2240 [ + - ]: 2991 : EditPaM aCursorPos;
2241 [ + + ][ + + ]: 2991 : if( pActiveView && !bSpellAtCursorPos )
2242 : : {
2243 : : DBG_CHKOBJ( pActiveView, EditView, 0 );
2244 [ + - ]: 3 : aCursorPos = pActiveView->pImpEditView->GetEditSelection().Max();
2245 : : }
2246 : 2991 : sal_Bool bRestartTimer = sal_False;
2247 : :
2248 [ + - ][ + - ]: 2991 : ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 );
2249 [ + - ]: 2991 : sal_uInt16 nNodes = GetEditDoc().Count();
2250 : 2991 : sal_uInt16 nInvalids = 0;
2251 [ + - ]: 2991 : Sequence< PropertyValue > aEmptySeq;
2252 [ + + ]: 6019 : for ( sal_uInt16 n = 0; n < nNodes; n++ )
2253 : : {
2254 [ + - ]: 3028 : ContentNode* pNode = GetEditDoc().GetObject( n );
2255 [ - + ]: 3028 : if ( pThisNodeOnly )
2256 : 0 : pNode = pThisNodeOnly;
2257 : :
2258 [ + - ][ + + ]: 3028 : if ( pNode->GetWrongList()->IsInvalid() )
2259 : : {
2260 : 2544 : WrongList* pWrongList = pNode->GetWrongList();
2261 : 2544 : sal_uInt16 nInvStart = pWrongList->GetInvalidStart();
2262 : 2544 : sal_uInt16 nInvEnd = pWrongList->GetInvalidEnd();
2263 : :
2264 : 2544 : sal_uInt16 nWrongs = 0; // Lose control also in the paragraphs
2265 : 2544 : sal_uInt16 nPaintFrom = 0xFFFF, nPaintTo = 0;
2266 : 2544 : sal_Bool bSimpleRepaint = sal_True;
2267 : :
2268 [ + - ]: 2544 : pWrongList->SetValid();
2269 : :
2270 [ + - ]: 2544 : EditPaM aPaM( pNode, nInvStart );
2271 [ + - ]: 2544 : EditSelection aSel( aPaM, aPaM );
2272 [ + - ][ + + ]: 5739 : while ( ( aSel.Max().GetNode() == pNode ) /* && !bStop */ )
2273 : : {
2274 [ + + ][ + + ]: 12015 : if ( ( aSel.Min().GetIndex() > nInvEnd )
[ + + ][ + + ]
2275 [ + - ][ + - ]: 6310 : || ( ( aSel.Max().GetNode() == pLastNode ) && ( aSel.Max().GetIndex() >= pLastNode->Len() ) ) )
2276 : : break; // Document end or end of invalid region
2277 : :
2278 [ + - ][ + - ]: 3195 : aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2279 [ + - ]: 3195 : String aWord( GetSelected( aSel ) );
2280 : : // If afterwards a dot, this must be handed over!
2281 : : // If an abbreviation ...
2282 : 3195 : sal_Bool bDottAdded = sal_False;
2283 [ + - ][ + - ]: 3195 : if ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() )
[ + + ]
2284 : : {
2285 [ + - ][ + - ]: 700 : sal_Unicode cNext = aSel.Max().GetNode()->GetChar( aSel.Max().GetIndex() );
2286 [ - + ]: 700 : if ( cNext == '.' )
2287 : : {
2288 : 0 : aSel.Max().GetIndex()++;
2289 [ # # ]: 0 : aWord += cNext;
2290 : 0 : bDottAdded = sal_True;
2291 : : }
2292 : : }
2293 : :
2294 : :
2295 : 3195 : sal_Bool bChanged = sal_False;
2296 [ + + ]: 3195 : if ( aWord.Len() > 0 )
2297 : : {
2298 : 3138 : sal_uInt16 nWStart = aSel.Min().GetIndex();
2299 : 3138 : sal_uInt16 nWEnd= aSel.Max().GetIndex();
2300 [ + - ][ + - ]: 3138 : if ( !xSpeller->isValid( aWord, GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) ), aEmptySeq ) )
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ]
2301 : : {
2302 : : // Check if already marked correctly...
2303 : 197 : nWrongs++;
2304 [ - + ]: 197 : sal_uInt16 nXEnd = bDottAdded ? nWEnd -1 : nWEnd;
2305 [ + - ][ + - ]: 197 : if ( !pWrongList->HasWrong( nWStart, nXEnd ) )
2306 : : {
2307 : : // Mark Word as wrong...
2308 : : // But only when not at Cursor-Position...
2309 : 197 : sal_Bool bCursorPos = sal_False;
2310 [ + - ][ - + ]: 197 : if ( aCursorPos.GetNode() == pNode )
2311 : : {
2312 [ # # ][ # # ]: 0 : if ( ( nWStart <= aCursorPos.GetIndex() ) && nWEnd >= aCursorPos.GetIndex() )
[ # # ]
2313 : 0 : bCursorPos = sal_True;
2314 : : }
2315 [ - + ]: 197 : if ( bCursorPos )
2316 : : {
2317 : : // Then continue to mark as invalid ...
2318 : 0 : pWrongList->GetInvalidStart() = nWStart;
2319 : 0 : pWrongList->GetInvalidEnd() = nWEnd;
2320 : 0 : bRestartTimer = sal_True;
2321 : : }
2322 : : else
2323 : : {
2324 : : // It may be that the Wrongs in the list ar not
2325 : : // spanning exactly over words because the
2326 : : // WordDelimiters during expansion are not
2327 : : // evaluated.
2328 [ + - ]: 197 : pWrongList->InsertWrong( nWStart, nXEnd, sal_True );
2329 : 197 : bChanged = sal_True;
2330 : : }
2331 : : }
2332 : : }
2333 : : else
2334 : : {
2335 : : // Check if not marked as wrong
2336 [ + - ][ - + ]: 2941 : if ( pWrongList->HasAnyWrong( nWStart, nWEnd ) )
2337 : : {
2338 [ # # ]: 0 : pWrongList->ClearWrongs( nWStart, nWEnd, pNode );
2339 : 0 : bSimpleRepaint = sal_False;
2340 : 0 : bChanged = sal_True;
2341 : : }
2342 : : }
2343 [ + + ]: 3138 : if ( bChanged )
2344 : : {
2345 [ + + ]: 197 : if ( nPaintFrom == 0xFFFF )
2346 : 196 : nPaintFrom = nWStart;
2347 : 197 : nPaintTo = nWEnd;
2348 : : }
2349 : : }
2350 : :
2351 [ + - ]: 3195 : EditPaM aLastEnd( aSel.Max() );
2352 [ + - ][ + - ]: 3195 : aSel = WordRight( aSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2353 [ + + ][ + - ]: 3391 : if ( bChanged && ( aSel.Min().GetNode() == pNode ) &&
[ + + - + ]
[ - + ]
2354 : 196 : ( ( aSel.Min().GetIndex()-aLastEnd.GetIndex() > 1 ) ) )
2355 : : {
2356 : : // If two words are separated by more than one blank, it
2357 : : // can happen that when splitting a Wrongs the start of
2358 : : // the second word is before the actually word
2359 [ # # ]: 0 : pWrongList->ClearWrongs( aLastEnd.GetIndex(), aSel.Min().GetIndex(), pNode );
2360 : : }
2361 [ + - ]: 5705 : }
2362 : :
2363 : : // Invalidate?
2364 [ + + ]: 2544 : if ( ( nPaintFrom != 0xFFFF ) )
2365 : : {
2366 : 196 : aStatus.GetStatusWord() |= EE_STAT_WRONGWORDCHANGED;
2367 [ + - ]: 196 : CallStatusHdl();
2368 : :
2369 [ - + ]: 196 : if (!aEditViews.empty())
2370 : : {
2371 : : // For SimpleRepaint one was painted over a range without
2372 : : // reaching VDEV, but then one would have to intersect, c
2373 : : // clipping, ... over all views. Probably not worthwhile.
2374 [ # # ]: 0 : EditPaM aStartPaM( pNode, nPaintFrom );
2375 [ # # ]: 0 : EditPaM aEndPaM( pNode, nPaintTo );
2376 [ # # ][ # # ]: 0 : Rectangle aStartCursor( PaMtoEditCursor( aStartPaM ) );
2377 [ # # ][ # # ]: 0 : Rectangle aEndCursor( PaMtoEditCursor( aEndPaM ) );
2378 : : DBG_ASSERT( aInvalidRec.IsEmpty(), "InvalidRect set!" );
2379 : 0 : aInvalidRec.Left() = 0;
2380 : 0 : aInvalidRec.Right() = GetPaperSize().Width();
2381 : 0 : aInvalidRec.Top() = aStartCursor.Top();
2382 : 0 : aInvalidRec.Bottom() = aEndCursor.Bottom();
2383 [ # # ][ # # ]: 0 : if ( pActiveView && pActiveView->HasSelection() )
[ # # ][ # # ]
2384 : : {
2385 : : // Then no output through VDev.
2386 [ # # ]: 0 : UpdateViews( NULL );
2387 : : }
2388 [ # # ]: 0 : else if ( bSimpleRepaint )
2389 : : {
2390 [ # # ]: 0 : for (size_t nView = 0; nView < aEditViews.size(); ++nView)
2391 : : {
2392 : 0 : EditView* pView = aEditViews[nView];
2393 : 0 : Rectangle aClipRec( aInvalidRec );
2394 [ # # ][ # # ]: 0 : aClipRec.Intersection( pView->GetVisArea() );
2395 [ # # ][ # # ]: 0 : if ( !aClipRec.IsEmpty() )
2396 : : {
2397 : : // convert to window coordinates ....
2398 [ # # ]: 0 : aClipRec.SetPos( pView->pImpEditView->GetWindowPos( aClipRec.TopLeft() ) );
2399 : : // If selected, then VDev ...
2400 [ # # ][ # # ]: 0 : Paint( pView->pImpEditView, aClipRec, pView->HasSelection() );
2401 : : }
2402 : : }
2403 : : }
2404 : : else
2405 : : {
2406 [ # # ]: 0 : UpdateViews( pActiveView );
2407 : : }
2408 [ # # ]: 0 : aInvalidRec = Rectangle();
2409 : : }
2410 : : }
2411 : : // After two corrected nodes give up the control ...
2412 : 2544 : nInvalids++;
2413 [ + + ][ - + ]: 2544 : if ( bInteruptable && ( nInvalids >= 2 ) )
2414 : : {
2415 : 2544 : bRestartTimer = sal_True;
2416 : : break;
2417 : : }
2418 : : }
2419 : :
2420 [ - + ]: 3028 : if ( pThisNodeOnly )
2421 : 0 : break;
2422 : : }
2423 [ - + ]: 2991 : if ( bRestartTimer )
2424 [ # # ][ + - ]: 3009 : aOnlineSpellTimer.Start();
2425 : : }
2426 : :
2427 : :
2428 : 0 : EESpellState ImpEditEngine::HasSpellErrors()
2429 : : {
2430 : : DBG_ASSERT( xSpeller.is(), "No spell checker set!" );
2431 : :
2432 [ # # ][ # # ]: 0 : ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 );
2433 [ # # ][ # # ]: 0 : EditSelection aCurSel( aEditDoc.GetStartPaM() );
2434 : :
2435 [ # # ]: 0 : String aWord;
2436 : 0 : Reference< XSpellAlternatives > xSpellAlt;
2437 [ # # ]: 0 : Sequence< PropertyValue > aEmptySeq;
2438 [ # # ]: 0 : while ( !xSpellAlt.is() )
2439 : : {
2440 [ # # ][ # # ]: 0 : if ( ( aCurSel.Max().GetNode() == pLastNode ) &&
[ # # ][ # # ]
2441 [ # # ]: 0 : ( aCurSel.Max().GetIndex() >= pLastNode->Len() ) )
2442 : : {
2443 : 0 : return EE_SPELL_OK;
2444 : : }
2445 : :
2446 [ # # ][ # # ]: 0 : aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2447 [ # # ][ # # ]: 0 : aWord = GetSelected( aCurSel );
[ # # ]
2448 [ # # ]: 0 : if ( aWord.Len() > 0 )
2449 : : {
2450 [ # # ]: 0 : LanguageType eLang = GetLanguage( aCurSel.Max() );
2451 [ # # ]: 0 : SvxSpellWrapper::CheckSpellLang( xSpeller, eLang );
2452 [ # # ][ # # ]: 0 : xSpellAlt = xSpeller->spell( aWord, eLang, aEmptySeq );
[ # # ][ # # ]
2453 : : }
2454 [ # # ][ # # ]: 0 : aCurSel = WordRight( aCurSel.Max(), ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2455 : : }
2456 : :
2457 [ # # ][ # # ]: 0 : return EE_SPELL_ERRORFOUND;
2458 : : }
2459 : :
2460 : 0 : EESpellState ImpEditEngine::StartThesaurus( EditView* pEditView )
2461 : : {
2462 [ # # ]: 0 : EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
2463 [ # # ][ # # ]: 0 : if ( !aCurSel.HasRange() )
2464 [ # # ][ # # ]: 0 : aCurSel = SelectWord( aCurSel, ::com::sun::star::i18n::WordType::DICTIONARY_WORD );
2465 [ # # ]: 0 : String aWord( GetSelected( aCurSel ) );
2466 : :
2467 [ # # ]: 0 : Reference< XThesaurus > xThes( SvxGetThesaurus() );
2468 [ # # ]: 0 : if (!xThes.is())
2469 : 0 : return EE_SPELL_ERRORFOUND;
2470 : :
2471 [ # # ]: 0 : EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
2472 [ # # ][ # # ]: 0 : AbstractThesaurusDialog* pDlg = pFact->CreateThesaurusDialog( pEditView->GetWindow(), xThes, aWord, GetLanguage( aCurSel.Max() ) );
[ # # ]
2473 [ # # ][ # # ]: 0 : if ( pDlg->Execute() == RET_OK )
2474 : : {
2475 : : // Replace Word...
2476 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2477 [ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aCurSel );
2478 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2479 [ # # ][ # # ]: 0 : pEditView->InsertText( pDlg->GetWord() );
[ # # ]
2480 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
2481 : : }
2482 : :
2483 [ # # ][ # # ]: 0 : delete pDlg;
2484 [ # # ]: 0 : return EE_SPELL_OK;
2485 : : }
2486 : :
2487 : 0 : sal_uInt16 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem )
2488 : : {
2489 : 0 : sal_uInt16 nFound = 0;
2490 : :
2491 [ # # ]: 0 : EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() );
2492 : :
2493 : : // FIND_ALL is not possible without multiple selection.
2494 [ # # # # ]: 0 : if ( ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND ) ||
[ # # ]
2495 : 0 : ( rSearchItem.GetCommand() == SVX_SEARCHCMD_FIND_ALL ) )
2496 : : {
2497 [ # # ][ # # ]: 0 : if ( Search( rSearchItem, pEditView ) )
2498 : 0 : nFound++;
2499 : : }
2500 [ # # ]: 0 : else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE )
2501 : : {
2502 : : // The word is selected if the user not altered the selection
2503 : : // in between:
2504 [ # # ][ # # ]: 0 : if ( aCurSel.HasRange() )
2505 : : {
2506 [ # # ][ # # ]: 0 : pEditView->InsertText( rSearchItem.GetReplaceString() );
[ # # ]
2507 : 0 : nFound = 1;
2508 : : }
2509 : : else
2510 [ # # ][ # # ]: 0 : if( Search( rSearchItem, pEditView ) )
2511 : 0 : nFound = 1;
2512 : : }
2513 [ # # ]: 0 : else if ( rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL )
2514 : : {
2515 : : // The Writer replaces all front beginning to end ...
2516 [ # # ]: 0 : SvxSearchItem aTmpItem( rSearchItem );
2517 : 0 : aTmpItem.SetBackward( sal_False );
2518 : :
2519 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2520 : :
2521 [ # # ]: 0 : aCurSel.Adjust( aEditDoc );
2522 [ # # ][ # # ]: 0 : EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : aEditDoc.GetStartPaM();
[ # # ]
2523 [ # # ]: 0 : EditSelection aFoundSel( aCurSel.Max() );
2524 [ # # ]: 0 : sal_Bool bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
2525 [ # # ]: 0 : if ( bFound )
2526 [ # # ]: 0 : UndoActionStart( EDITUNDO_REPLACEALL );
2527 [ # # ]: 0 : while ( bFound )
2528 : : {
2529 : 0 : nFound++;
2530 [ # # ][ # # ]: 0 : aStartPaM = ImpInsertText( aFoundSel, rSearchItem.GetReplaceString() );
[ # # ][ # # ]
2531 [ # # ]: 0 : bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel );
2532 : : }
2533 [ # # ]: 0 : if ( nFound )
2534 : : {
2535 [ # # ]: 0 : EditPaM aNewPaM( aFoundSel.Max() );
2536 [ # # ][ # # ]: 0 : if ( aNewPaM.GetIndex() > aNewPaM.GetNode()->Len() )
[ # # ]
2537 [ # # ][ # # ]: 0 : aNewPaM.GetIndex() = aNewPaM.GetNode()->Len();
2538 [ # # ][ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aNewPaM );
2539 [ # # ]: 0 : FormatAndUpdate( pEditView );
2540 [ # # ]: 0 : UndoActionEnd( EDITUNDO_REPLACEALL );
2541 : : }
2542 : : else
2543 : : {
2544 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2545 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
2546 [ # # ]: 0 : }
2547 : : }
2548 : 0 : return nFound;
2549 : : }
2550 : :
2551 : 0 : sal_Bool ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditView )
2552 : : {
2553 [ # # ]: 0 : EditSelection aSel( pEditView->pImpEditView->GetEditSelection() );
2554 [ # # ]: 0 : aSel.Adjust( aEditDoc );
2555 [ # # ]: 0 : EditPaM aStartPaM( aSel.Max() );
2556 [ # # ][ # # ]: 0 : if ( rSearchItem.GetSelection() && !rSearchItem.GetBackward() )
[ # # ]
2557 [ # # ]: 0 : aStartPaM = aSel.Min();
2558 : :
2559 [ # # ]: 0 : EditSelection aFoundSel;
2560 [ # # ]: 0 : sal_Bool bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
2561 [ # # ][ # # ]: 0 : if ( bFound && ( aFoundSel == aSel ) ) // For backwards-search
[ # # ][ # # ]
2562 : : {
2563 [ # # ]: 0 : aStartPaM = aSel.Min();
2564 [ # # ]: 0 : bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel );
2565 : : }
2566 : :
2567 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2568 [ # # ]: 0 : if ( bFound )
2569 : : {
2570 : : // First, set the minimum, so the whole word is in the visible range.
2571 [ # # ][ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aFoundSel.Min() );
2572 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
2573 [ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aFoundSel );
2574 : : }
2575 : : else
2576 [ # # ][ # # ]: 0 : pEditView->pImpEditView->SetEditSelection( aSel.Max() );
2577 : :
2578 [ # # ]: 0 : pEditView->pImpEditView->DrawSelection();
2579 [ # # ]: 0 : pEditView->ShowCursor( sal_True, sal_False );
2580 : 0 : return bFound;
2581 : : }
2582 : :
2583 : 0 : sal_Bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem,
2584 : : const EditSelection& rSearchSelection, const EditPaM& rStartPos, EditSelection& rFoundSel )
2585 : : {
2586 : 0 : util::SearchOptions aSearchOptions( rSearchItem.GetSearchOptions() );
2587 [ # # ]: 0 : aSearchOptions.Locale = GetLocale( rStartPos );
2588 : :
2589 : 0 : sal_Bool bBack = rSearchItem.GetBackward();
2590 : 0 : sal_Bool bSearchInSelection = rSearchItem.GetSelection();
2591 [ # # ][ # # ]: 0 : sal_uInt16 nStartNode = aEditDoc.GetPos( rStartPos.GetNode() );
2592 : : sal_uInt16 nEndNode;
2593 [ # # ]: 0 : if ( bSearchInSelection )
2594 : : {
2595 [ # # ][ # # ]: 0 : nEndNode = aEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() );
[ # # ][ # # ]
2596 : : }
2597 : : else
2598 : : {
2599 [ # # ][ # # ]: 0 : nEndNode = bBack ? 0 : aEditDoc.Count()-1;
2600 : : }
2601 : :
2602 [ # # ]: 0 : utl::TextSearch aSearcher( aSearchOptions );
2603 : :
2604 : : // iterate over the paragraphs ...
2605 [ # # ][ # # ]: 0 : for ( sal_uInt16 nNode = nStartNode;
[ # # ]
2606 : : bBack ? ( nNode >= nEndNode ) : ( nNode <= nEndNode) ;
2607 : : bBack ? nNode-- : nNode++ )
2608 : : {
2609 : : // For backwards-search if nEndNode = 0:
2610 [ # # ]: 0 : if ( nNode >= 0xFFFF )
2611 : 0 : return sal_False;
2612 : :
2613 [ # # ]: 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
2614 : :
2615 : 0 : sal_uInt16 nStartPos = 0;
2616 [ # # ]: 0 : sal_uInt16 nEndPos = pNode->Len();
2617 [ # # ]: 0 : if ( nNode == nStartNode )
2618 : : {
2619 [ # # ]: 0 : if ( bBack )
2620 : 0 : nEndPos = rStartPos.GetIndex();
2621 : : else
2622 : 0 : nStartPos = rStartPos.GetIndex();
2623 : : }
2624 [ # # ][ # # ]: 0 : if ( ( nNode == nEndNode ) && bSearchInSelection )
2625 : : {
2626 [ # # ]: 0 : if ( bBack )
2627 : 0 : nStartPos = rSearchSelection.Min().GetIndex();
2628 : : else
2629 : 0 : nEndPos = rSearchSelection.Max().GetIndex();
2630 : : }
2631 : :
2632 : : // Searching ...
2633 [ # # ]: 0 : XubString aParaStr( GetEditDoc().GetParaAsString( pNode ) );
2634 : 0 : bool bFound = false;
2635 [ # # ]: 0 : if ( bBack )
2636 : : {
2637 : 0 : Swapsal_uIt16s( nStartPos, nEndPos );
2638 [ # # ]: 0 : bFound = aSearcher.SearchBkwrd( aParaStr, &nStartPos, &nEndPos);
2639 : : }
2640 : : else
2641 [ # # ]: 0 : bFound = aSearcher.SearchFrwrd( aParaStr, &nStartPos, &nEndPos);
2642 : :
2643 [ # # ]: 0 : if ( bFound )
2644 : : {
2645 [ # # ]: 0 : rFoundSel.Min().SetNode( pNode );
2646 : 0 : rFoundSel.Min().SetIndex( nStartPos );
2647 [ # # ]: 0 : rFoundSel.Max().SetNode( pNode );
2648 : 0 : rFoundSel.Max().SetIndex( nEndPos );
2649 : 0 : return sal_True;
2650 : : }
2651 [ # # ][ # # ]: 0 : }
2652 [ # # ]: 0 : return sal_False;
2653 : : }
2654 : :
2655 : 0 : sal_Bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem )
2656 : : {
2657 [ # # ]: 0 : SvxSearchItem aTmpItem( rSearchItem );
2658 : 0 : aTmpItem.SetBackward( sal_False );
2659 [ # # ]: 0 : aTmpItem.SetSelection( sal_False );
2660 : :
2661 [ # # ]: 0 : EditPaM aStartPaM( aEditDoc.GetStartPaM() );
2662 [ # # ]: 0 : EditSelection aDummySel( aStartPaM );
2663 [ # # ]: 0 : EditSelection aFoundSel;
2664 [ # # ][ # # ]: 0 : return ImpSearch( aTmpItem, aDummySel, aStartPaM, aFoundSel );
2665 : : }
2666 : :
2667 : 0 : void ImpEditEngine::SetAutoCompleteText( const String& rStr, sal_Bool bClearTipWindow )
2668 : : {
2669 : 0 : aAutoCompleteText = rStr;
2670 [ # # ][ # # ]: 0 : if ( bClearTipWindow && pActiveView )
2671 [ # # ][ # # ]: 0 : Help::ShowQuickHelp( pActiveView->GetWindow(), Rectangle(), String(), 0 );
[ # # ]
2672 : 0 : }
2673 : :
2674 : : namespace
2675 : : {
2676 [ # # ][ # # ]: 0 : struct eeTransliterationChgData
[ # # ]
2677 : : {
2678 : : sal_uInt16 nStart;
2679 : : xub_StrLen nLen;
2680 : : EditSelection aSelection;
2681 : : String aNewText;
2682 : : uno::Sequence< sal_Int32 > aOffsets;
2683 : : };
2684 : : }
2685 : :
2686 : 0 : EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, sal_Int32 nTransliterationMode )
2687 : : {
2688 [ # # ]: 0 : uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
2689 [ # # ]: 0 : if (!_xBI.is())
2690 [ # # ]: 0 : return rSelection;
2691 : :
2692 [ # # ]: 0 : EditSelection aSel( rSelection );
2693 [ # # ]: 0 : aSel.Adjust( aEditDoc );
2694 : :
2695 [ # # ][ # # ]: 0 : if ( !aSel.HasRange() )
2696 [ # # ][ # # ]: 0 : aSel = SelectWord( aSel );
2697 : :
2698 [ # # ]: 0 : EditSelection aNewSel( aSel );
2699 : :
2700 [ # # ][ # # ]: 0 : const sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
2701 [ # # ][ # # ]: 0 : const sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
2702 : :
2703 : 0 : sal_Bool bChanges = sal_False;
2704 : 0 : sal_Bool bLenChanged = sal_False;
2705 : 0 : EditUndoTransliteration* pUndo = NULL;
2706 : :
2707 [ # # ][ # # ]: 0 : utl::TransliterationWrapper aTranslitarationWrapper( ::comphelper::getProcessServiceFactory(), nTransliterationMode );
2708 [ # # ]: 0 : sal_Bool bConsiderLanguage = aTranslitarationWrapper.needLanguageForTheMode();
2709 : :
2710 [ # # ]: 0 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
2711 : : {
2712 [ # # ]: 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
2713 [ # # ]: 0 : const XubString& aNodeStr = pNode->GetString();
2714 : 0 : xub_StrLen nStartPos = 0;
2715 : 0 : xub_StrLen nEndPos = aNodeStr.Len();
2716 [ # # ]: 0 : if ( nNode == nStartNode )
2717 : 0 : nStartPos = aSel.Min().GetIndex();
2718 [ # # ]: 0 : if ( nNode == nEndNode ) // can also be == nStart!
2719 : 0 : nEndPos = aSel.Max().GetIndex();
2720 : :
2721 : 0 : sal_uInt16 nCurrentStart = nStartPos;
2722 : 0 : sal_uInt16 nCurrentEnd = nEndPos;
2723 : 0 : sal_uInt16 nLanguage = LANGUAGE_SYSTEM;
2724 : :
2725 : : // since we don't use Hiragana/Katakana or half-width/full-width transliterations here
2726 : : // it is fine to use ANYWORD_IGNOREWHITESPACES. (ANY_WORD btw is broken and will
2727 : : // occasionaly miss words in consecutive sentences). Also with ANYWORD_IGNOREWHITESPACES
2728 : : // text like 'just-in-time' will be converted to 'Just-In-Time' which seems to be the
2729 : : // proper thing to do.
2730 : 0 : const sal_Int16 nWordType = i18n::WordType::ANYWORD_IGNOREWHITESPACES;
2731 : :
2732 : : //! In order to have less trouble with changing text size, e.g. because
2733 : : //! of ligatures or � (German small sz) being resolved, we need to process
2734 : : //! the text replacements from end to start.
2735 : : //! This way the offsets for the yet to be changed words will be
2736 : : //! left unchanged by the already replaced text.
2737 : : //! For this we temporarily save the changes to be done in this vector
2738 [ # # ]: 0 : std::vector< eeTransliterationChgData > aChanges;
2739 [ # # ]: 0 : eeTransliterationChgData aChgData;
2740 : :
2741 [ # # ]: 0 : if (nTransliterationMode == i18n::TransliterationModulesExtra::TITLE_CASE)
2742 : : {
2743 : : // for 'capitalize every word' we need to iterate over each word
2744 : :
2745 : 0 : i18n::Boundary aSttBndry;
2746 : 0 : i18n::Boundary aEndBndry;
2747 [ # # ]: 0 : aSttBndry = _xBI->getWordBoundary(
2748 : : aNodeStr, nStartPos,
2749 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nStartPos + 1 ) ) ),
2750 [ # # ][ # # ]: 0 : nWordType, true /*prefer forward direction*/);
[ # # ]
2751 [ # # ]: 0 : aEndBndry = _xBI->getWordBoundary(
2752 : : aNodeStr, nEndPos,
2753 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nEndPos + 1 ) ) ),
2754 [ # # ][ # # ]: 0 : nWordType, false /*prefer backward direction*/);
[ # # ]
2755 : :
2756 : : // prevent backtracking to the previous word if selection is at word boundary
2757 [ # # ]: 0 : if (aSttBndry.endPos <= nStartPos)
2758 : : {
2759 [ # # ]: 0 : aSttBndry = _xBI->nextWord(
2760 : : aNodeStr, aSttBndry.endPos,
2761 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, aSttBndry.endPos + 1 ) ) ),
2762 [ # # ][ # # ]: 0 : nWordType);
[ # # ]
2763 : : }
2764 : : // prevent advancing to the next word if selection is at word boundary
2765 [ # # ]: 0 : if (aEndBndry.startPos >= nEndPos)
2766 : : {
2767 [ # # ]: 0 : aEndBndry = _xBI->previousWord(
2768 : : aNodeStr, aEndBndry.startPos,
2769 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, aEndBndry.startPos + 1 ) ) ),
2770 [ # # ][ # # ]: 0 : nWordType);
[ # # ]
2771 : : }
2772 : :
2773 : 0 : i18n::Boundary aCurWordBndry( aSttBndry );
2774 [ # # ]: 0 : while (aCurWordBndry.startPos <= aEndBndry.startPos)
2775 : : {
2776 : 0 : nCurrentStart = (xub_StrLen)aCurWordBndry.startPos;
2777 : 0 : nCurrentEnd = (xub_StrLen)aCurWordBndry.endPos;
2778 : 0 : sal_Int32 nLen = nCurrentEnd - nCurrentStart;
2779 : : DBG_ASSERT( nLen > 0, "invalid word length of 0" );
2780 : : #if OSL_DEBUG_LEVEL > 1
2781 : : String aText(aNodeStr.Copy(nCurrentStart, nLen) );
2782 : : #endif
2783 : :
2784 [ # # ]: 0 : Sequence< sal_Int32 > aOffsets;
2785 : : String aNewText( aTranslitarationWrapper.transliterate(aNodeStr,
2786 [ # # ][ # # ]: 0 : GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ),
2787 [ # # ]: 0 : nCurrentStart, nLen, &aOffsets ));
2788 : :
2789 [ # # ][ # # ]: 0 : if (!aNodeStr.Equals( aNewText, nCurrentStart, nLen ))
2790 : : {
2791 : 0 : aChgData.nStart = nCurrentStart;
2792 : 0 : aChgData.nLen = nLen;
2793 [ # # ][ # # ]: 0 : aChgData.aSelection = EditSelection( EditPaM( pNode, nCurrentStart ), EditPaM( pNode, nCurrentEnd ) );
[ # # ][ # # ]
2794 [ # # ]: 0 : aChgData.aNewText = aNewText;
2795 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
2796 [ # # ]: 0 : aChanges.push_back( aChgData );
2797 : : }
2798 : : #if OSL_DEBUG_LEVEL > 1
2799 : : String aSelTxt ( GetSelected( aChgData.aSelection ) );
2800 : : (void) aSelTxt;
2801 : : #endif
2802 : :
2803 [ # # ]: 0 : aCurWordBndry = _xBI->nextWord(aNodeStr, nCurrentEnd,
2804 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentEnd + 1 ) ) ),
2805 [ # # ][ # # ]: 0 : nWordType);
[ # # ]
2806 [ # # ][ # # ]: 0 : }
2807 : : DBG_ASSERT( nCurrentEnd >= aEndBndry.endPos, "failed to reach end of transliteration" );
2808 : : }
2809 [ # # ]: 0 : else if (nTransliterationMode == i18n::TransliterationModulesExtra::SENTENCE_CASE)
2810 : : {
2811 : : // for 'sentence case' we need to iterate sentence by sentence
2812 : :
2813 [ # # ]: 0 : sal_Int32 nLastStart = _xBI->beginOfSentence(
2814 : : aNodeStr, nEndPos,
2815 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nEndPos + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2816 [ # # ]: 0 : sal_Int32 nLastEnd = _xBI->endOfSentence(
2817 : : aNodeStr, nLastStart,
2818 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nLastStart + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2819 : :
2820 : : // extend nCurrentStart, nCurrentEnd to the current sentence boundaries
2821 [ # # ]: 0 : nCurrentStart = _xBI->beginOfSentence(
2822 : : aNodeStr, nStartPos,
2823 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nStartPos + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2824 [ # # ]: 0 : nCurrentEnd = _xBI->endOfSentence(
2825 : : aNodeStr, nCurrentStart,
2826 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2827 : :
2828 : : // prevent backtracking to the previous sentence if selection starts at end of a sentence
2829 [ # # ]: 0 : if (nCurrentEnd <= nStartPos)
2830 : : {
2831 : : // now nCurrentStart is probably located on a non-letter word. (unless we
2832 : : // are in Asian text with no spaces...)
2833 : : // Thus to get the real sentence start we should locate the next real word,
2834 : : // that is one found by DICTIONARY_WORD
2835 [ # # ]: 0 : i18n::Boundary aBndry = _xBI->nextWord( aNodeStr, nCurrentEnd,
2836 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentEnd + 1 ) ) ),
2837 [ # # ][ # # ]: 0 : i18n::WordType::DICTIONARY_WORD);
[ # # ]
2838 : :
2839 : : // now get new current sentence boundaries
2840 [ # # ]: 0 : nCurrentStart = _xBI->beginOfSentence(
2841 : : aNodeStr, aBndry.startPos,
2842 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, aBndry.startPos + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2843 [ # # ]: 0 : nCurrentEnd = _xBI->endOfSentence(
2844 : : aNodeStr, nCurrentStart,
2845 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2846 : : }
2847 : : // prevent advancing to the next sentence if selection ends at start of a sentence
2848 [ # # ]: 0 : if (nLastStart >= nEndPos)
2849 : : {
2850 : : // now nCurrentStart is probably located on a non-letter word. (unless we
2851 : : // are in Asian text with no spaces...)
2852 : : // Thus to get the real sentence start we should locate the previous real word,
2853 : : // that is one found by DICTIONARY_WORD
2854 [ # # ]: 0 : i18n::Boundary aBndry = _xBI->previousWord( aNodeStr, nLastStart,
2855 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nLastStart + 1 ) ) ),
2856 [ # # ][ # # ]: 0 : i18n::WordType::DICTIONARY_WORD);
[ # # ]
2857 [ # # ]: 0 : nLastEnd = _xBI->endOfSentence(
2858 : : aNodeStr, aBndry.startPos,
2859 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, aBndry.startPos + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2860 [ # # ]: 0 : if (nCurrentEnd > nLastEnd)
2861 : 0 : nCurrentEnd = nLastEnd;
2862 : : }
2863 : :
2864 [ # # ]: 0 : while (nCurrentStart < nLastEnd)
2865 : : {
2866 : 0 : sal_Int32 nLen = nCurrentEnd - nCurrentStart;
2867 : : DBG_ASSERT( nLen > 0, "invalid word length of 0" );
2868 : : #if OSL_DEBUG_LEVEL > 1
2869 : : String aText( aNodeStr.Copy( nCurrentStart, nLen ) );
2870 : : #endif
2871 : :
2872 [ # # ]: 0 : Sequence< sal_Int32 > aOffsets;
2873 : : String aNewText( aTranslitarationWrapper.transliterate( aNodeStr,
2874 [ # # ][ # # ]: 0 : GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ),
2875 [ # # ]: 0 : nCurrentStart, nLen, &aOffsets ));
2876 : :
2877 [ # # ][ # # ]: 0 : if (!aNodeStr.Equals( aNewText, nCurrentStart, nLen ))
2878 : : {
2879 : 0 : aChgData.nStart = nCurrentStart;
2880 : 0 : aChgData.nLen = nLen;
2881 [ # # ][ # # ]: 0 : aChgData.aSelection = EditSelection( EditPaM( pNode, nCurrentStart ), EditPaM( pNode, nCurrentEnd ) );
[ # # ][ # # ]
2882 [ # # ]: 0 : aChgData.aNewText = aNewText;
2883 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
2884 [ # # ]: 0 : aChanges.push_back( aChgData );
2885 : : }
2886 : :
2887 : 0 : i18n::Boundary aFirstWordBndry;
2888 [ # # ]: 0 : aFirstWordBndry = _xBI->nextWord(
2889 : : aNodeStr, nCurrentEnd,
2890 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentEnd + 1 ) ) ),
2891 [ # # ][ # # ]: 0 : nWordType);
[ # # ]
2892 : 0 : nCurrentStart = aFirstWordBndry.startPos;
2893 [ # # ]: 0 : nCurrentEnd = _xBI->endOfSentence(
2894 : : aNodeStr, nCurrentStart,
2895 [ # # ][ # # ]: 0 : SvxCreateLocale( GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ) ) );
[ # # ][ # # ]
[ # # ]
2896 [ # # ][ # # ]: 0 : }
2897 : : DBG_ASSERT( nCurrentEnd >= nLastEnd, "failed to reach end of transliteration" );
2898 : : }
2899 : : else
2900 : : {
2901 [ # # ]: 0 : do
2902 : : {
2903 [ # # ]: 0 : if ( bConsiderLanguage )
2904 : : {
2905 [ # # ][ # # ]: 0 : nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd );
2906 [ # # ]: 0 : if ( nCurrentEnd > nEndPos )
2907 : 0 : nCurrentEnd = nEndPos;
2908 : : }
2909 : :
2910 : 0 : xub_StrLen nLen = nCurrentEnd - nCurrentStart;
2911 : :
2912 [ # # ]: 0 : Sequence< sal_Int32 > aOffsets;
2913 [ # # ]: 0 : String aNewText( aTranslitarationWrapper.transliterate( aNodeStr, nLanguage, nCurrentStart, nLen, &aOffsets ) );
2914 : :
2915 [ # # ][ # # ]: 0 : if (!aNodeStr.Equals( aNewText, nCurrentStart, nLen ))
2916 : : {
2917 : 0 : aChgData.nStart = nCurrentStart;
2918 : 0 : aChgData.nLen = nLen;
2919 [ # # ][ # # ]: 0 : aChgData.aSelection = EditSelection( EditPaM( pNode, nCurrentStart ), EditPaM( pNode, nCurrentEnd ) );
[ # # ][ # # ]
2920 [ # # ]: 0 : aChgData.aNewText = aNewText;
2921 [ # # ]: 0 : aChgData.aOffsets = aOffsets;
2922 [ # # ]: 0 : aChanges.push_back( aChgData );
2923 : : }
2924 : :
2925 [ # # ][ # # ]: 0 : nCurrentStart = nCurrentEnd;
2926 : : } while( nCurrentEnd < nEndPos );
2927 : : }
2928 : :
2929 [ # # ]: 0 : if (!aChanges.empty())
2930 : : {
2931 : : // Create a single UndoAction on Demand for all the changes ...
2932 [ # # ][ # # ]: 0 : if ( !pUndo && IsUndoEnabled() && !IsInUndo() )
[ # # ][ # # ]
2933 : : {
2934 : : // adjust selection to include all changes
2935 [ # # ]: 0 : for (size_t i = 0; i < aChanges.size(); ++i)
2936 : : {
2937 : 0 : const EditSelection &rSel = aChanges[i].aSelection;
2938 [ # # ]: 0 : if (aSel.Min().GetNode() == rSel.Min().GetNode() &&
[ # # # # ]
[ # # ][ # # ]
2939 : 0 : aSel.Min().GetIndex() > rSel.Min().GetIndex())
2940 : 0 : aSel.Min().SetIndex( rSel.Min().GetIndex() );
2941 [ # # ][ # # ]: 0 : if (aSel.Max().GetNode() == rSel.Max().GetNode() &&
[ # # # # ]
[ # # ]
2942 : 0 : aSel.Max().GetIndex() < rSel.Max().GetIndex())
2943 : 0 : aSel.Max().SetIndex( rSel.Max().GetIndex() );
2944 : : }
2945 [ # # ]: 0 : aNewSel = aSel;
2946 : :
2947 [ # # ]: 0 : ESelection aESel( CreateESel( aSel ) );
2948 [ # # ][ # # ]: 0 : pUndo = new EditUndoTransliteration(pEditEngine, aESel, nTransliterationMode);
2949 : :
2950 [ # # ][ # # ]: 0 : const bool bSingleNode = aSel.Min().GetNode()== aSel.Max().GetNode();
2951 [ # # ][ # # ]: 0 : const bool bHasAttribs = aSel.Min().GetNode()->GetCharAttribs().HasAttrib( aSel.Min().GetIndex(), aSel.Max().GetIndex() );
2952 [ # # ][ # # ]: 0 : if (bSingleNode && !bHasAttribs)
2953 [ # # ][ # # ]: 0 : pUndo->SetText( aSel.Min().GetNode()->Copy( aSel.Min().GetIndex(), aSel.Max().GetIndex()-aSel.Min().GetIndex() ) );
[ # # ][ # # ]
2954 : : else
2955 [ # # ][ # # ]: 0 : pUndo->SetText( CreateBinTextObject( aSel, NULL ) );
2956 : : }
2957 : :
2958 : : // now apply the changes from end to start to leave the offsets of the
2959 : : // yet unchanged text parts remain the same.
2960 [ # # ]: 0 : for (size_t i = 0; i < aChanges.size(); ++i)
2961 : : {
2962 : 0 : eeTransliterationChgData& rData = aChanges[ aChanges.size() - 1 - i ];
2963 : :
2964 : 0 : bChanges = sal_True;
2965 [ # # ]: 0 : if (rData.nLen != rData.aNewText.Len())
2966 : 0 : bLenChanged = sal_True;
2967 : :
2968 : : // Change text without loosing the attributes
2969 : 0 : sal_uInt16 nDiffs = ReplaceTextOnly( rData.aSelection.Min().GetNode(),
2970 [ # # ][ # # ]: 0 : rData.nStart, rData.nLen, rData.aNewText, rData.aOffsets );
2971 : :
2972 : : // adjust selection in end node to possibly changed size
2973 [ # # ][ # # ]: 0 : if (aSel.Max().GetNode() == rData.aSelection.Max().GetNode())
[ # # ]
2974 : 0 : aNewSel.Max().GetIndex() = aNewSel.Max().GetIndex() + nDiffs;
2975 : :
2976 [ # # ][ # # ]: 0 : sal_uInt16 nSelNode = aEditDoc.GetPos( rData.aSelection.Min().GetNode() );
2977 [ # # ]: 0 : ParaPortion* pParaPortion = GetParaPortions()[nSelNode];
2978 : : pParaPortion->MarkSelectionInvalid( rData.nStart,
2979 : : std::max< sal_uInt16 >( rData.nStart + rData.nLen,
2980 [ # # ][ # # ]: 0 : rData.nStart + rData.aNewText.Len() ) );
2981 : : }
2982 : : }
2983 [ # # ]: 0 : }
2984 : :
2985 [ # # ]: 0 : if ( pUndo )
2986 : : {
2987 [ # # ]: 0 : ESelection aESel( CreateESel( aNewSel ) );
2988 : 0 : pUndo->SetNewSelection( aESel );
2989 [ # # ]: 0 : InsertUndo( pUndo );
2990 : : }
2991 : :
2992 [ # # ]: 0 : if ( bChanges )
2993 : : {
2994 [ # # ]: 0 : TextModified();
2995 [ # # ]: 0 : SetModifyFlag( sal_True );
2996 [ # # ]: 0 : if ( bLenChanged )
2997 [ # # ]: 0 : UpdateSelections();
2998 [ # # ]: 0 : FormatAndUpdate();
2999 : : }
3000 : :
3001 [ # # ][ # # ]: 0 : return aNewSel;
3002 : : }
3003 : :
3004 : :
3005 : 0 : short ImpEditEngine::ReplaceTextOnly(
3006 : : ContentNode* pNode,
3007 : : sal_uInt16 nCurrentStart, xub_StrLen nLen,
3008 : : const String& rNewText,
3009 : : const uno::Sequence< sal_Int32 >& rOffsets )
3010 : : {
3011 : : (void) nLen;
3012 : :
3013 : : // Change text without loosing the attributes
3014 : : sal_uInt16 nCharsAfterTransliteration =
3015 : 0 : sal::static_int_cast< sal_uInt16 >(rOffsets.getLength());
3016 : 0 : const sal_Int32* pOffsets = rOffsets.getConstArray();
3017 : 0 : short nDiffs = 0;
3018 [ # # ]: 0 : for ( sal_uInt16 n = 0; n < nCharsAfterTransliteration; n++ )
3019 : : {
3020 : 0 : sal_uInt16 nCurrentPos = nCurrentStart+n;
3021 : 0 : sal_Int32 nDiff = (nCurrentPos-nDiffs) - pOffsets[n];
3022 : :
3023 [ # # ]: 0 : if ( !nDiff )
3024 : : {
3025 : : DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
3026 : 0 : pNode->SetChar( nCurrentPos, rNewText.GetChar(n) );
3027 : : }
3028 [ # # ]: 0 : else if ( nDiff < 0 )
3029 : : {
3030 : : // Replace first char, delete the rest...
3031 : : DBG_ASSERT( nCurrentPos < pNode->Len(), "TransliterateText - String smaller than expected!" );
3032 : 0 : pNode->SetChar( nCurrentPos, rNewText.GetChar(n) );
3033 : :
3034 : : DBG_ASSERT( (nCurrentPos+1) < pNode->Len(), "TransliterateText - String smaller than expected!" );
3035 [ # # ]: 0 : GetEditDoc().RemoveChars( EditPaM( pNode, nCurrentPos+1 ), sal::static_int_cast< sal_uInt16 >(-nDiff) );
3036 : : }
3037 : : else
3038 : : {
3039 : : DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." );
3040 [ # # ][ # # ]: 0 : GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), rtl::OUString(rNewText.GetChar(n)) );
[ # # ][ # # ]
3041 : :
3042 : : }
3043 : 0 : nDiffs = sal::static_int_cast< short >(nDiffs + nDiff);
3044 : : }
3045 : :
3046 : 0 : return nDiffs;
3047 : : }
3048 : :
3049 : :
3050 : 44731 : void ImpEditEngine::SetAsianCompressionMode( sal_uInt16 n )
3051 : : {
3052 [ + + ]: 44731 : if ( n != nAsianCompressionMode )
3053 : : {
3054 : 10 : nAsianCompressionMode = n;
3055 [ - + ]: 10 : if ( ImplHasText() )
3056 : : {
3057 : 0 : FormatFullDoc();
3058 : 0 : UpdateViews();
3059 : : }
3060 : : }
3061 : 44731 : }
3062 : :
3063 : 44731 : void ImpEditEngine::SetKernAsianPunctuation( bool b )
3064 : : {
3065 [ + + ]: 44731 : if ( b != bKernAsianPunctuation )
3066 : : {
3067 : 4 : bKernAsianPunctuation = b;
3068 [ - + ]: 4 : if ( ImplHasText() )
3069 : : {
3070 : 0 : FormatFullDoc();
3071 : 0 : UpdateViews();
3072 : : }
3073 : : }
3074 : 44731 : }
3075 : :
3076 : 42987 : void ImpEditEngine::SetAddExtLeading( bool bExtLeading )
3077 : : {
3078 [ + + ]: 42987 : if ( IsAddExtLeading() != bExtLeading )
3079 : : {
3080 : 2834 : bAddExtLeading = bExtLeading;
3081 [ - + ]: 2834 : if ( ImplHasText() )
3082 : : {
3083 : 0 : FormatFullDoc();
3084 : 0 : UpdateViews();
3085 : : }
3086 : : }
3087 : 42987 : };
3088 : :
3089 : :
3090 : :
3091 : 2848 : sal_Bool ImpEditEngine::ImplHasText() const
3092 : : {
3093 [ + - ][ - + ]: 2848 : return ( ( GetEditDoc().Count() > 1 ) || GetEditDoc().GetObject(0)->Len() );
3094 : : }
3095 : :
3096 : 0 : sal_Int32 ImpEditEngine::LogicToTwips(sal_Int32 n)
3097 : : {
3098 : 0 : Size aSz(n, 0);
3099 [ # # ]: 0 : MapMode aTwipsMode( MAP_TWIP );
3100 [ # # ]: 0 : aSz = pRefDev->LogicToLogic( aSz, NULL, &aTwipsMode );
3101 [ # # ]: 0 : return aSz.Width();
3102 : : }
3103 : :
3104 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|