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