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