Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <hintids.hxx>
21 : #include <view.hxx>
22 : #include <wrtsh.hxx>
23 : #include <swundo.hxx>
24 : #include <globals.hrc>
25 : #include <splargs.hxx>
26 :
27 : #include <vcl/msgbox.hxx>
28 : #include <editeng/unolingu.hxx>
29 : #include <editeng/langitem.hxx>
30 : #include <editeng/fontitem.hxx>
31 : #include <rtl/ustring.hxx>
32 : #include <com/sun/star/text/RubyAdjust.hpp>
33 : #include <hhcwrp.hxx>
34 : #include <sdrhhcwrap.hxx>
35 : #include <doc.hxx>
36 : #include <docsh.hxx>
37 : #include <mdiexp.hxx>
38 : #include <edtwin.hxx>
39 : #include <crsskip.hxx>
40 : #include <index.hxx>
41 : #include <pam.hxx>
42 : #include <swcrsr.hxx>
43 : #include <viscrs.hxx>
44 : #include <ndtxt.hxx>
45 : #include <fmtruby.hxx>
46 : #include <breakit.hxx>
47 :
48 : #include <olmenu.hrc>
49 :
50 : #include <unomid.h>
51 :
52 : using namespace ::com::sun::star;
53 : using namespace ::com::sun::star::text;
54 : using namespace ::com::sun::star::uno;
55 : using namespace ::com::sun::star::linguistic2;
56 : using namespace ::com::sun::star::i18n;
57 :
58 : // Description: Turn off frame/object shell if applicable
59 :
60 4 : static void lcl_ActivateTextShell( SwWrtShell & rWrtSh )
61 : {
62 4 : if( rWrtSh.IsSelFrmMode() || rWrtSh.IsObjSelected() )
63 0 : rWrtSh.EnterStdMode();
64 4 : }
65 :
66 : class SwKeepConversionDirectionStateContext
67 : {
68 : public:
69 0 : SwKeepConversionDirectionStateContext()
70 : {
71 : //!! hack to transport the current conversion direction state settings
72 : //!! into the next incarnation that iterates over the drawing objets
73 : //!! ( see SwHHCWrapper::~SwHHCWrapper() )
74 0 : editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( true );
75 0 : }
76 :
77 0 : ~SwKeepConversionDirectionStateContext()
78 : {
79 0 : editeng::HangulHanjaConversion::SetUseSavedConversionDirectionState( false );
80 0 : }
81 : };
82 :
83 8 : SwHHCWrapper::SwHHCWrapper(
84 : SwView* pSwView,
85 : const uno::Reference< uno::XComponentContext >& rxContext,
86 : LanguageType nSourceLanguage,
87 : LanguageType nTargetLanguage,
88 : const vcl::Font *pTargetFont,
89 : sal_Int32 nConvOptions,
90 : bool bIsInteractive,
91 : bool bStart, bool bOther, bool bSelection )
92 8 : : editeng::HangulHanjaConversion( &pSwView->GetEditWin(), rxContext,
93 : LanguageTag::convertToLocale( nSourceLanguage ),
94 : LanguageTag::convertToLocale( nTargetLanguage ),
95 : pTargetFont,
96 : nConvOptions,
97 : bIsInteractive )
98 : , m_pView( pSwView )
99 8 : , m_pWin( &pSwView->GetEditWin() )
100 8 : , m_rWrtShell( pSwView->GetWrtShell() )
101 : , m_pConvArgs( 0 )
102 : , m_nLastPos( 0 )
103 : , m_nUnitOffset( 0 )
104 : , m_nPageCount( 0 )
105 : , m_nPageStart( 0 )
106 : , m_bIsDrawObj( false )
107 : , m_bIsOtherCntnt( bOther )
108 : , m_bStartChk( bOther )
109 : , m_bIsSelection( bSelection )
110 8 : , m_bStartDone( bOther || bStart )
111 40 : , m_bEndDone( false )
112 : {
113 8 : }
114 :
115 16 : SwHHCWrapper::~SwHHCWrapper()
116 : {
117 8 : delete m_pConvArgs;
118 :
119 8 : SwViewShell::SetCareWin( NULL );
120 :
121 : // check for existence of a draw view which means that there are
122 : // (or previously were) draw objects present in the document.
123 : // I.e. we like to check those too.
124 8 : if ( IsDrawObj() /*&& bLastRet*/ && m_pView->GetWrtShell().HasDrawView() )
125 : {
126 0 : vcl::Cursor *pSave = m_pView->GetWindow()->GetCursor();
127 : {
128 0 : SwKeepConversionDirectionStateContext aContext;
129 :
130 0 : SdrHHCWrapper aSdrConvWrap( m_pView, GetSourceLanguage(),
131 0 : GetTargetLanguage(), GetTargetFont(),
132 0 : GetConversionOptions(), IsInteractive() );
133 0 : aSdrConvWrap.StartTextConversion();
134 : }
135 0 : m_pView->GetWindow()->SetCursor( pSave );
136 : }
137 :
138 8 : if( m_nPageCount )
139 8 : ::EndProgress( m_pView->GetDocShell() );
140 :
141 : // finally for chinese translation we need to change the documents
142 : // default language and font to the new ones to be used.
143 8 : LanguageType nTargetLang = GetTargetLanguage();
144 8 : if (IsChinese( nTargetLang ))
145 : {
146 8 : SwDoc *pDoc = m_pView->GetDocShell()->GetDoc();
147 :
148 : //!! Note: This also effects the default language of text boxes (EditEngine/EditView) !!
149 8 : pDoc->SetDefault( SvxLanguageItem( nTargetLang, RES_CHRATR_CJK_LANGUAGE ) );
150 :
151 8 : const vcl::Font *pFont = GetTargetFont();
152 8 : if (pFont)
153 : {
154 0 : SvxFontItem aFontItem( pFont->GetFamily(), pFont->GetName(),
155 0 : pFont->GetStyleName(), pFont->GetPitch(),
156 0 : pFont->GetCharSet(), RES_CHRATR_CJK_FONT );
157 0 : pDoc->SetDefault( aFontItem );
158 : }
159 :
160 : }
161 8 : }
162 :
163 12 : void SwHHCWrapper::GetNextPortion(
164 : OUString& rNextPortion,
165 : LanguageType& rLangOfPortion,
166 : bool bAllowChanges )
167 : {
168 12 : m_pConvArgs->bAllowImplicitChangesForNotConvertibleText = bAllowChanges;
169 :
170 12 : FindConvText_impl();
171 12 : rNextPortion = m_pConvArgs->aConvText;
172 12 : rLangOfPortion = m_pConvArgs->nConvTextLang;
173 :
174 12 : m_nUnitOffset = 0;
175 :
176 : // build last pos from currently selected text
177 12 : SwPaM* pCrsr = m_rWrtShell.GetCrsr();
178 12 : m_nLastPos = pCrsr->Start()->nContent.GetIndex();
179 12 : }
180 :
181 4 : void SwHHCWrapper::SelectNewUnit_impl( sal_Int32 nUnitStart, sal_Int32 nUnitEnd )
182 : {
183 4 : SwPaM *pCrsr = m_rWrtShell.GetCrsr();
184 4 : pCrsr->GetPoint()->nContent = m_nLastPos;
185 4 : pCrsr->DeleteMark();
186 :
187 : m_rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ false,
188 4 : (sal_uInt16) (m_nUnitOffset + nUnitStart), true );
189 4 : pCrsr->SetMark();
190 : m_rWrtShell.Right( CRSR_SKIP_CHARS, /*bExpand*/ true,
191 4 : (sal_uInt16) (nUnitEnd - nUnitStart), true );
192 : // end selection now. Otherwise SHIFT+HOME (extending the selection)
193 : // won't work when the dialog is closed without any replacement.
194 : // (see #116346#)
195 4 : m_rWrtShell.EndSelect();
196 4 : }
197 :
198 0 : void SwHHCWrapper::HandleNewUnit(
199 : const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd )
200 : {
201 : OSL_ENSURE( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" );
202 0 : if (!(0 <= nUnitStart && nUnitStart <= nUnitEnd))
203 0 : return;
204 :
205 0 : lcl_ActivateTextShell( m_rWrtShell );
206 :
207 0 : m_rWrtShell.StartAllAction();
208 :
209 : // select current unit
210 0 : SelectNewUnit_impl( nUnitStart, nUnitEnd );
211 :
212 0 : m_rWrtShell.EndAllAction();
213 : }
214 :
215 4 : void SwHHCWrapper::ChangeText( const OUString &rNewText,
216 : const OUString& rOrigText,
217 : const uno::Sequence< sal_Int32 > *pOffsets,
218 : SwPaM *pCrsr )
219 : {
220 : //!! please see also TextConvWrapper::ChangeText with is a modified
221 : //!! copy of this code
222 :
223 : OSL_ENSURE( !rNewText.isEmpty(), "unexpected empty string" );
224 4 : if (rNewText.isEmpty())
225 4 : return;
226 :
227 4 : if (pOffsets && pCrsr) // try to keep as much attributation as possible ?
228 : {
229 : // remember cursor start position for later setting of the cursor
230 4 : const SwPosition *pStart = pCrsr->Start();
231 4 : const sal_Int32 nStartIndex = pStart->nContent.GetIndex();
232 4 : const SwNodeIndex aStartNodeIndex = pStart->nNode;
233 4 : SwTxtNode *pStartTxtNode = aStartNodeIndex.GetNode().GetTxtNode();
234 :
235 4 : const sal_Int32 nIndices = pOffsets->getLength();
236 4 : const sal_Int32 *pIndices = pOffsets->getConstArray();
237 4 : sal_Int32 nConvTextLen = rNewText.getLength();
238 4 : sal_Int32 nPos = 0;
239 4 : sal_Int32 nChgPos = -1;
240 4 : sal_Int32 nChgLen = 0;
241 4 : sal_Int32 nConvChgPos = -1;
242 4 : sal_Int32 nConvChgLen = 0;
243 :
244 : // offset to calculate the position in the text taking into
245 : // account that text may have been replaced with new text of
246 : // different length. Negative values allowed!
247 4 : long nCorrectionOffset = 0;
248 :
249 : OSL_ENSURE(nIndices == 0 || nIndices == nConvTextLen,
250 : "mismatch between string length and sequence length!" );
251 :
252 : // find all substrings that need to be replaced (and only those)
253 : while (true)
254 : {
255 : // get index in original text that matches nPos in new text
256 : sal_Int32 nIndex;
257 8 : if (nPos < nConvTextLen)
258 4 : nIndex = nPos < nIndices ? pIndices[nPos] : nPos;
259 : else
260 : {
261 4 : nPos = nConvTextLen;
262 4 : nIndex = rOrigText.getLength();
263 : }
264 :
265 12 : if (nPos == nConvTextLen || /* end of string also terminates non-matching char sequence */
266 4 : rOrigText[nIndex] == rNewText[nPos])
267 : {
268 : // substring that needs to be replaced found?
269 4 : if (nChgPos != -1 && nConvChgPos != -1)
270 : {
271 4 : nChgLen = nIndex - nChgPos;
272 4 : nConvChgLen = nPos - nConvChgPos;
273 : #if OSL_DEBUG_LEVEL > 1
274 : OUString aInOrig( rOrigText.copy( nChgPos, nChgLen ) );
275 : #endif
276 4 : OUString aInNew( rNewText.copy( nConvChgPos, nConvChgLen ) );
277 :
278 : // set selection to sub string to be replaced in original text
279 4 : sal_Int32 nChgInNodeStartIndex = nStartIndex + nCorrectionOffset + nChgPos;
280 : OSL_ENSURE( m_rWrtShell.GetCrsr()->HasMark(), "cursor misplaced (nothing selected)" );
281 4 : m_rWrtShell.GetCrsr()->GetMark()->nContent.Assign( pStartTxtNode, nChgInNodeStartIndex );
282 4 : m_rWrtShell.GetCrsr()->GetPoint()->nContent.Assign( pStartTxtNode, nChgInNodeStartIndex + nChgLen );
283 : #if OSL_DEBUG_LEVEL > 1
284 : OUString aSelTxt1( m_rWrtShell.GetSelTxt() );
285 : #endif
286 :
287 : // replace selected sub string with the corresponding
288 : // sub string from the new text while keeping as
289 : // much from the attributes as possible
290 4 : ChangeText_impl( aInNew, true );
291 :
292 4 : nCorrectionOffset += nConvChgLen - nChgLen;
293 :
294 4 : nChgPos = -1;
295 4 : nConvChgPos = -1;
296 : }
297 : }
298 : else
299 : {
300 : // begin of non-matching char sequence found ?
301 4 : if (nChgPos == -1 && nConvChgPos == -1)
302 : {
303 4 : nChgPos = nIndex;
304 4 : nConvChgPos = nPos;
305 : }
306 : }
307 8 : if (nPos >= nConvTextLen)
308 4 : break;
309 4 : ++nPos;
310 : }
311 :
312 : // set cursor to the end of all the new text
313 : // (as it would happen after ChangeText_impl (Delete and Insert)
314 : // of the whole text in the 'else' branch below)
315 4 : m_rWrtShell.ClearMark();
316 4 : m_rWrtShell.GetCrsr()->Start()->nContent.Assign( pStartTxtNode, nStartIndex + nConvTextLen );
317 : }
318 : else
319 : {
320 0 : ChangeText_impl( rNewText, false );
321 : }
322 : }
323 :
324 4 : void SwHHCWrapper::ChangeText_impl( const OUString &rNewText, bool bKeepAttributes )
325 : {
326 4 : if (bKeepAttributes)
327 : {
328 : // get item set with all relevant attributes
329 : sal_uInt16 aRanges[] = {
330 : RES_CHRATR_BEGIN, RES_FRMATR_END,
331 4 : 0, 0, 0 };
332 4 : SfxItemSet aItemSet( m_rWrtShell.GetAttrPool(), aRanges );
333 : // get all attributes spanning the whole selection in order to
334 : // restore those for the new text
335 4 : m_rWrtShell.GetCurAttr( aItemSet );
336 :
337 : #if OSL_DEBUG_LEVEL > 1
338 : OUString aSelTxt1( m_rWrtShell.GetSelTxt() );
339 : #endif
340 4 : m_rWrtShell.Delete();
341 4 : m_rWrtShell.Insert( rNewText );
342 :
343 : // select new inserted text (currently the Point is right after the new text)
344 4 : if (!m_rWrtShell.GetCrsr()->HasMark())
345 4 : m_rWrtShell.GetCrsr()->SetMark();
346 4 : SwPosition *pMark = m_rWrtShell.GetCrsr()->GetMark();
347 4 : pMark->nContent = pMark->nContent.GetIndex() - rNewText.getLength();
348 : #if OSL_DEBUG_LEVEL > 1
349 : OUString aSelTxt2( m_rWrtShell.GetSelTxt() );
350 : #endif
351 :
352 : // since 'SetAttr' below functions like merging with the attributes
353 : // from the itemset with any existing ones we have to get rid of all
354 : // all attributes now. (Those attributes that may take effect left
355 : // to the position where the new text gets inserted after the old text
356 : // was deleted)
357 4 : m_rWrtShell.ResetAttr();
358 : // apply previously saved attributes to new text
359 4 : m_rWrtShell.SetAttrSet( aItemSet );
360 : }
361 : else
362 : {
363 0 : m_rWrtShell.Delete();
364 0 : m_rWrtShell.Insert( rNewText );
365 : }
366 4 : }
367 :
368 4 : void SwHHCWrapper::ReplaceUnit(
369 : const sal_Int32 nUnitStart, const sal_Int32 nUnitEnd,
370 : const OUString& rOrigText,
371 : const OUString& rReplaceWith,
372 : const uno::Sequence< sal_Int32 > &rOffsets,
373 : ReplacementAction eAction,
374 : LanguageType *pNewUnitLanguage )
375 : {
376 : OSL_ENSURE( nUnitStart >= 0 && nUnitEnd >= nUnitStart, "wrong arguments" );
377 4 : if (!(nUnitStart >= 0 && nUnitEnd >= nUnitStart))
378 4 : return;
379 :
380 4 : lcl_ActivateTextShell( m_rWrtShell );
381 :
382 : // replace the current word
383 4 : m_rWrtShell.StartAllAction();
384 :
385 : // select current unit
386 4 : SelectNewUnit_impl( nUnitStart, nUnitEnd );
387 :
388 4 : OUString aOrigTxt( m_rWrtShell.GetSelTxt() );
389 8 : OUString aNewTxt( rReplaceWith );
390 : OSL_ENSURE( aOrigTxt == rOrigText, "!! text mismatch !!" );
391 4 : SwFmtRuby *pRuby = 0;
392 4 : bool bRubyBelow = false;
393 8 : OUString aNewOrigText;
394 4 : switch (eAction)
395 : {
396 : case eExchange :
397 4 : break;
398 : case eReplacementBracketed :
399 : {
400 0 : aNewTxt = aOrigTxt + "(" + rReplaceWith + ")";
401 : }
402 0 : break;
403 : case eOriginalBracketed :
404 : {
405 0 : aNewTxt = rReplaceWith + "(" + aOrigTxt + ")";
406 : }
407 0 : break;
408 : case eReplacementAbove :
409 : {
410 0 : pRuby = new SwFmtRuby( rReplaceWith );
411 : }
412 0 : break;
413 : case eOriginalAbove :
414 : {
415 0 : pRuby = new SwFmtRuby( aOrigTxt );
416 0 : aNewOrigText = rReplaceWith;
417 : }
418 0 : break;
419 : case eReplacementBelow :
420 : {
421 0 : pRuby = new SwFmtRuby( rReplaceWith );
422 0 : bRubyBelow = true;
423 : }
424 0 : break;
425 : case eOriginalBelow :
426 : {
427 0 : pRuby = new SwFmtRuby( aOrigTxt );
428 0 : aNewOrigText = rReplaceWith;
429 0 : bRubyBelow = true;
430 : }
431 0 : break;
432 : default:
433 : OSL_FAIL("unexpected case" );
434 : }
435 4 : m_nUnitOffset += nUnitStart + aNewTxt.getLength();
436 :
437 4 : if (pRuby)
438 : {
439 0 : m_rWrtShell.StartUndo( UNDO_SETRUBYATTR );
440 0 : if (!aNewOrigText.isEmpty())
441 : {
442 : // according to FT we currently should not bother about keeping
443 : // attributes in Hangul/Hanja conversion
444 0 : ChangeText( aNewOrigText, rOrigText, NULL, NULL );
445 :
446 : //!! since Delete, Insert in 'ChangeText' do not set the WrtShells
447 : //!! bInSelect flag
448 : //!! back to false we do it now manually in order for the selection
449 : //!! to be done properly in the following call to Left.
450 : // We didn't fix it in Delete and Insert since it is currently
451 : // unclear if someone depends on this incorrect behvaiour
452 : // of the flag.
453 0 : m_rWrtShell.EndSelect();
454 :
455 0 : m_rWrtShell.Left( 0, true, aNewOrigText.getLength(), true, true );
456 : }
457 :
458 0 : pRuby->SetPosition( static_cast<sal_uInt16>(bRubyBelow) );
459 0 : pRuby->SetAdjustment( RubyAdjust_CENTER );
460 :
461 : #if OSL_DEBUG_LEVEL > 1
462 : SwPaM *pPaM = m_rWrtShell.GetCrsr();
463 : (void)pPaM;
464 : #endif
465 0 : m_rWrtShell.SetAttrItem(*pRuby);
466 0 : delete pRuby;
467 0 : m_rWrtShell.EndUndo( UNDO_SETRUBYATTR );
468 : }
469 : else
470 : {
471 4 : m_rWrtShell.StartUndo( UNDO_OVERWRITE );
472 :
473 : // according to FT we should currently not bother about keeping
474 : // attributes in Hangul/Hanja conversion and leave that untouched.
475 : // Thus we do this only for Chinese translation...
476 4 : const bool bIsChineseConversion = IsChinese( GetSourceLanguage() );
477 4 : if (bIsChineseConversion)
478 4 : ChangeText( aNewTxt, rOrigText, &rOffsets, m_rWrtShell.GetCrsr() );
479 : else
480 0 : ChangeText( aNewTxt, rOrigText, NULL, NULL );
481 :
482 : // change language and font if necessary
483 4 : if (bIsChineseConversion)
484 : {
485 4 : m_rWrtShell.SetMark();
486 4 : m_rWrtShell.GetCrsr()->GetMark()->nContent -= aNewTxt.getLength();
487 :
488 : OSL_ENSURE( GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED || GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL,
489 : "SwHHCWrapper::ReplaceUnit : unexpected target language" );
490 :
491 : sal_uInt16 aRanges[] = {
492 : RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
493 : RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
494 4 : 0, 0, 0 };
495 :
496 4 : SfxItemSet aSet( m_rWrtShell.GetAttrPool(), aRanges );
497 4 : if (pNewUnitLanguage)
498 : {
499 2 : aSet.Put( SvxLanguageItem( *pNewUnitLanguage, RES_CHRATR_CJK_LANGUAGE ) );
500 : }
501 :
502 4 : const vcl::Font *pTargetFont = GetTargetFont();
503 : OSL_ENSURE( pTargetFont, "target font missing?" );
504 4 : if (pTargetFont && pNewUnitLanguage)
505 : {
506 0 : SvxFontItem aFontItem = (SvxFontItem&) aSet.Get( RES_CHRATR_CJK_FONT );
507 0 : aFontItem.SetFamilyName( pTargetFont->GetName());
508 0 : aFontItem.SetFamily( pTargetFont->GetFamily());
509 0 : aFontItem.SetStyleName( pTargetFont->GetStyleName());
510 0 : aFontItem.SetPitch( pTargetFont->GetPitch());
511 0 : aFontItem.SetCharSet( pTargetFont->GetCharSet() );
512 0 : aSet.Put( aFontItem );
513 : }
514 :
515 4 : m_rWrtShell.SetAttrSet( aSet );
516 :
517 4 : m_rWrtShell.ClearMark();
518 : }
519 :
520 4 : m_rWrtShell.EndUndo( UNDO_OVERWRITE );
521 : }
522 :
523 8 : m_rWrtShell.EndAllAction();
524 : }
525 :
526 0 : bool SwHHCWrapper::HasRubySupport() const
527 : {
528 0 : return true;
529 : }
530 :
531 8 : void SwHHCWrapper::Convert()
532 : {
533 : OSL_ENSURE( m_pConvArgs == 0, "NULL pointer expected" );
534 : {
535 8 : SwPaM *pCrsr = m_pView->GetWrtShell().GetCrsr();
536 8 : SwPosition* pSttPos = pCrsr->Start();
537 8 : SwPosition* pEndPos = pCrsr->End();
538 :
539 16 : if (pSttPos->nNode.GetNode().IsTxtNode() &&
540 8 : pEndPos->nNode.GetNode().IsTxtNode())
541 : {
542 8 : m_pConvArgs = new SwConversionArgs( GetSourceLanguage(),
543 8 : pSttPos->nNode.GetNode().GetTxtNode(), pSttPos->nContent,
544 16 : pEndPos->nNode.GetNode().GetTxtNode(), pEndPos->nContent );
545 : }
546 : else // we are not in the text (maybe a graphic or OLE object is selected) let's start from the top
547 : {
548 : // get PaM that points to the start of the document
549 0 : SwNode& rNode = m_pView->GetDocShell()->GetDoc()->GetNodes().GetEndOfContent();
550 0 : SwPaM aPam(rNode);
551 0 : aPam.Move( fnMoveBackward, fnGoDoc ); // move to start of document
552 :
553 0 : pSttPos = aPam.GetPoint(); //! using a PaM here makes sure we will get only text nodes
554 0 : SwTxtNode *pTxtNode = pSttPos->nNode.GetNode().GetTxtNode();
555 : // just in case we check anyway...
556 0 : if (!pTxtNode || !pTxtNode->IsTxtNode())
557 8 : return;
558 0 : m_pConvArgs = new SwConversionArgs( GetSourceLanguage(),
559 : pTxtNode, pSttPos->nContent,
560 0 : pTxtNode, pSttPos->nContent );
561 : }
562 : OSL_ENSURE( m_pConvArgs->pStartNode && m_pConvArgs->pStartNode->IsTxtNode(),
563 : "failed to get proper start text node" );
564 : OSL_ENSURE( m_pConvArgs->pEndNode && m_pConvArgs->pEndNode->IsTxtNode(),
565 : "failed to get proper end text node" );
566 :
567 : // chinese conversion specific settings
568 : OSL_ENSURE( IsChinese( GetSourceLanguage() ) == IsChinese( GetTargetLanguage() ),
569 : "source and target language mismatch?" );
570 8 : if (IsChinese( GetTargetLanguage() ))
571 : {
572 8 : m_pConvArgs->nConvTargetLang = GetTargetLanguage();
573 8 : m_pConvArgs->pTargetFont = GetTargetFont();
574 8 : m_pConvArgs->bAllowImplicitChangesForNotConvertibleText = true;
575 : }
576 :
577 : // if it is not just a selection and we are about to begin
578 : // with the current conversion for the very first time
579 : // we need to find the start of the current (initial)
580 : // convertible unit in order for the text conversion to give
581 : // the correct result for that. Since it is easier to obtain
582 : // the start of the word we use that though.
583 8 : if (!pCrsr->HasMark()) // is not a selection?
584 : {
585 : // since #118246 / #117803 still occurs if the cursor is placed
586 : // between the two chinese characters to be converted (because both
587 : // of them are words on their own!) using the word boundary here does
588 : // not work. Thus since chinese conversion is not interactive we start
589 : // at the begin of the paragraph to solve the problem, i.e. have the
590 : // TextConversion service get those characters together in the same call.
591 8 : sal_Int32 nStartIdx = -1;
592 8 : if (editeng::HangulHanjaConversion::IsChinese( GetSourceLanguage() ) )
593 8 : nStartIdx = 0;
594 : else
595 : {
596 0 : OUString aText( m_pConvArgs->pStartNode->GetTxt() );
597 0 : const sal_Int32 nPos = m_pConvArgs->pStartIdx->GetIndex();
598 0 : Boundary aBoundary( g_pBreakIt->GetBreakIter()->
599 0 : getWordBoundary( aText, nPos, g_pBreakIt->GetLocale( m_pConvArgs->nConvSrcLang ),
600 0 : WordType::DICTIONARY_WORD, sal_True ) );
601 :
602 : // valid result found?
603 0 : if (aBoundary.startPos < aText.getLength() &&
604 0 : aBoundary.startPos != aBoundary.endPos)
605 : {
606 0 : nStartIdx = aBoundary.startPos;
607 0 : }
608 : }
609 :
610 8 : if (nStartIdx != -1)
611 8 : *m_pConvArgs->pStartIdx = nStartIdx;
612 : }
613 : }
614 :
615 8 : if ( m_bIsOtherCntnt )
616 0 : ConvStart_impl( m_pConvArgs, SVX_SPELL_OTHER );
617 : else
618 : {
619 8 : m_bStartChk = false;
620 8 : ConvStart_impl( m_pConvArgs, SVX_SPELL_BODY_END );
621 : }
622 :
623 8 : ConvertDocument();
624 :
625 8 : ConvEnd_impl( m_pConvArgs );
626 : }
627 :
628 8 : bool SwHHCWrapper::ConvNext_impl( )
629 : {
630 : //! modified version of SvxSpellWrapper::SpellNext
631 :
632 : // no change of direction so the desired region is fully processed
633 8 : if( m_bStartChk )
634 0 : m_bStartDone = true;
635 : else
636 8 : m_bEndDone = true;
637 :
638 8 : if( m_bIsOtherCntnt && m_bStartDone && m_bEndDone ) // document completely checked?
639 : {
640 0 : return false;
641 : }
642 :
643 8 : bool bGoOn = false;
644 :
645 8 : if ( m_bIsOtherCntnt )
646 : {
647 0 : m_bStartChk = false;
648 0 : ConvStart_impl( m_pConvArgs, SVX_SPELL_BODY );
649 0 : bGoOn = true;
650 : }
651 8 : else if ( m_bStartDone && m_bEndDone )
652 : {
653 : // body region done, ask about special region
654 16 : if( HasOtherCnt_impl() )
655 : {
656 0 : ConvStart_impl( m_pConvArgs, SVX_SPELL_OTHER );
657 0 : m_bIsOtherCntnt = bGoOn = true;
658 : }
659 : }
660 : else
661 : {
662 0 : m_bStartChk = !m_bStartDone;
663 0 : ConvStart_impl( m_pConvArgs, m_bStartChk ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
664 0 : bGoOn = true;
665 : }
666 8 : return bGoOn;
667 : }
668 :
669 12 : bool SwHHCWrapper::FindConvText_impl()
670 : {
671 : //! modified version of SvxSpellWrapper::FindSpellError
672 :
673 12 : bool bFound = false;
674 :
675 12 : m_pWin->EnterWait();
676 12 : bool bConv = true;
677 :
678 36 : while ( bConv )
679 : {
680 12 : bFound = ConvContinue_impl( m_pConvArgs );
681 12 : if (bFound)
682 : {
683 4 : bConv = false;
684 : }
685 : else
686 : {
687 8 : ConvEnd_impl( m_pConvArgs );
688 8 : bConv = ConvNext_impl();
689 : }
690 : }
691 12 : m_pWin->LeaveWait();
692 12 : return bFound;
693 : }
694 :
695 8 : bool SwHHCWrapper::HasOtherCnt_impl()
696 : {
697 8 : return m_bIsSelection ? false : m_rWrtShell.HasOtherCnt();
698 : }
699 :
700 8 : void SwHHCWrapper::ConvStart_impl( SwConversionArgs /* [out] */ *pConversionArgs, SvxSpellArea eArea )
701 : {
702 8 : SetDrawObj( SVX_SPELL_OTHER == eArea );
703 8 : m_pView->SpellStart( eArea, m_bStartDone, m_bEndDone, /* [out] */ pConversionArgs );
704 8 : }
705 :
706 16 : void SwHHCWrapper::ConvEnd_impl( SwConversionArgs *pConversionArgs )
707 : {
708 16 : m_pView->SpellEnd( pConversionArgs );
709 16 : }
710 :
711 12 : bool SwHHCWrapper::ConvContinue_impl( SwConversionArgs *pConversionArgs )
712 : {
713 12 : bool bProgress = !m_bIsDrawObj && !m_bIsSelection;
714 12 : pConversionArgs->aConvText = OUString();
715 12 : pConversionArgs->nConvTextLang = LANGUAGE_NONE;
716 12 : m_pView->GetWrtShell().SpellContinue( &m_nPageCount, bProgress ? &m_nPageStart : NULL, pConversionArgs );
717 12 : return !pConversionArgs->aConvText.isEmpty();
718 270 : }
719 :
720 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|