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