Update ooo320-m1
[ooovba.git] / svx / source / dialog / hyphen.cxx
blob81ae5961cf31d5280626c1bcbab29c692d2f3798
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hyphen.cxx,v $
10 * $Revision: 1.14 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 // include ---------------------------------------------------------------
35 #include <tools/shl.hxx>
36 #include <tools/list.hxx>
37 #include <com/sun/star/linguistic2/XPossibleHyphens.hpp>
38 #include <vcl/msgbox.hxx>
41 #define _SVX_HYPHEN_CXX
43 #include <svx/dialogs.hrc>
44 #include "hyphen.hrc"
46 #include <svx/svxenum.hxx>
47 #include "hyphen.hxx"
48 #include <svx/splwrap.hxx>
49 #include "dlgutil.hxx"
50 #include <svx/dialmgr.hxx>
51 #include <unolingu.hxx>
52 #ifndef _USR_USTRING_HXX
53 //#include <usr/ustring.hxx>
54 #endif
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::beans;
59 using namespace ::com::sun::star::linguistic2;
61 #undef S2U
62 #undef U2S
63 //#define S2U(s) StringToOUString(s, CHARSET_SYSTEM)
64 //#define U2S(s) OUStringToString(s, CHARSET_SYSTEM)
66 // define ----------------------------------------------------------------
68 #define HYPHHERE '-'
69 #define CONTINUE_HYPH USHRT_MAX
71 // Dies ist nur ein Hack, weil an dieser Stelle das extern char aus hmwrap
72 // nicht bekannt ist, wird demnaechst in hmwrap durch ein define ersetzt.
73 #define SW_SOFT_HYPHEN '='
75 // class SvxHyphenEdit ---------------------------------------------------
77 SvxHyphenEdit::SvxHyphenEdit( Window* pParent, const ResId& rResId ) :
79 Edit( pParent, rResId )
83 // -----------------------------------------------------------------------
85 void SvxHyphenEdit::KeyInput( const KeyEvent& rKEvt )
87 // sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
88 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
90 switch ( nCode )
92 case KEY_LEFT:
93 ( (SvxHyphenWordDialog*)GetParent() )->SelLeft();
94 break;
96 case KEY_RIGHT:
97 ( (SvxHyphenWordDialog*)GetParent() )->SelRight();
98 break;
100 case KEY_TAB:
101 case KEY_ESCAPE:
102 case KEY_RETURN:
103 Edit::KeyInput(rKEvt);
104 break;
105 default:
106 Control::KeyInput( rKEvt ); // An den Dialog weiterleiten
107 break;
111 // class SvxHyphenWordDialog ---------------------------------------------
113 SvxHyphenWordDialog::SvxHyphenWordDialog( const String &rWord, LanguageType nLang,
114 Window* pParent,
115 Reference< XHyphenator > &xHyphen,
116 SvxSpellWrapper* pWrapper ) :
117 SfxModalDialog( pParent, SVX_RES( RID_SVXDLG_HYPHENATE ) ),
119 aWordFT ( this, SVX_RES( FT_WORD ) ),
120 aWordEdit ( this, SVX_RES( ED_WORD ) ),
121 aLeftBtn ( this, SVX_RES( BTN_LEFT ) ),
122 aRightBtn ( this, SVX_RES( BTN_RIGHT ) ),
123 aOkBtn ( this, SVX_RES( BTN_HYPH_CUT ) ),
124 aCancelBtn ( this, SVX_RES( BTN_HYPH_CANCEL ) ),
125 aContBtn ( this, SVX_RES( BTN_HYPH_CONTINUE ) ),
126 aDelBtn ( this, SVX_RES( BTN_HYPH_DELETE ) ),
127 aHelpBtn ( this, SVX_RES( BTN_HYPH_HELP ) ),
128 aLabel ( GetText() ),
129 pHyphWrapper ( pWrapper ),
130 xHyphenator ( xHyphen ),
131 aActWord ( rWord ),
132 nActLanguage ( nLang ),
133 nHyphPos ( 0 ),
134 nOldPos ( 0 ),
135 bBusy ( sal_False )
137 aContBtn.SetClickHdl(
138 LINK( this, SvxHyphenWordDialog, ContinueHdl_Impl ) );
139 aOkBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, CutHdl_Impl ) );
140 aDelBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, DeleteHdl_Impl ) );
141 aCancelBtn.SetClickHdl(
142 LINK( this, SvxHyphenWordDialog, CancelHdl_Impl ) );
143 aLeftBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, Left_Impl ) );
144 aRightBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, Right_Impl ) );
146 aWordEdit.SetGetFocusHdl(
147 LINK( this, SvxHyphenWordDialog, GetFocusHdl_Impl ) );
149 Reference< XHyphenatedWord > xHyphWord( pWrapper ?
150 pWrapper->GetLast() : Reference< XInterface > () , UNO_QUERY );
151 DBG_ASSERT(xHyphWord.is(), "missing hyphenated word");
152 nMaxHyphenationPos = xHyphWord.is() ? xHyphWord->getHyphenationPos() : 0;
153 SetLabel_Impl( nLang );
155 InitControls_Impl();
156 aWordEdit.GrabFocus();
158 FreeResource();
160 // disable controls if service is not available
161 if (!xHyphenator.is())
162 Enable( sal_False );
165 // -----------------------------------------------------------------------
167 void SvxHyphenWordDialog::SelLeft()
169 String aTxt( aWordEdit.GetText() );
171 for ( xub_StrLen i = nOldPos + 1; i-- > 0 ; )
173 DBG_ASSERT(i <= aTxt.Len(), "index out of range");
174 if( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
176 aTxt.SetChar( i, sal_Unicode( HYPHHERE ) );
178 if ( nOldPos != 0 && nOldPos != aTxt.Len() )
179 aTxt.SetChar( nOldPos, sal_Unicode( SW_SOFT_HYPHEN ) );
180 nOldPos = i;
181 aWordEdit.SetText( aTxt );
182 aWordEdit.GrabFocus();
183 aWordEdit.SetSelection( Selection( i, i + 1 ) );
184 break;
187 nHyphPos = GetHyphIndex_Impl();
188 EnableLRBtn_Impl();
191 // -----------------------------------------------------------------------
193 void SvxHyphenWordDialog::SelRight()
195 String aTxt( aWordEdit.GetText() );
197 for ( xub_StrLen i = nOldPos + 1; i < aTxt.Len(); ++i )
199 if( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
201 aTxt.SetChar( i, sal_Unicode( HYPHHERE ) );
203 if ( nOldPos != 0 && nOldPos != aTxt.Len() )
204 aTxt.SetChar( nOldPos, sal_Unicode( SW_SOFT_HYPHEN ) );
205 nOldPos = i;
206 aWordEdit.SetText( aTxt );
207 aWordEdit.GrabFocus();
208 aWordEdit.SetSelection( Selection( i, i + 1 ) );
209 break;
212 nHyphPos = GetHyphIndex_Impl();
213 EnableLRBtn_Impl();
216 // -----------------------------------------------------------------------
218 void SvxHyphenWordDialog::EnableLRBtn_Impl()
220 String aTxt( aWordEdit.GetText() );
221 xub_StrLen nLen = aTxt.Len();
222 xub_StrLen i;
224 aRightBtn.Disable();
225 for ( i = nOldPos + 2; i < nLen; ++i )
227 if ( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
229 aRightBtn.Enable();
230 break;
234 DBG_ASSERT(nOldPos < aTxt.Len(), "nOldPos out of range");
235 if (nOldPos >= aTxt.Len())
236 nOldPos = aTxt.Len() - 1;
237 aLeftBtn.Disable();
238 for ( i = nOldPos; i-- > 0; )
240 if ( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
242 aLeftBtn.Enable();
243 break;
248 // -----------------------------------------------------------------------
251 void SvxHyphenWordDialog::SetLabel_Impl( LanguageType nLang )
253 String aLangStr( ::GetLanguageString( nLang ) );
254 String aTmp( aLabel );
255 aTmp.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
256 aTmp.Append( aLangStr );
257 aTmp.Append( sal_Unicode( ')' ) );
258 SetText( aTmp );
261 // -----------------------------------------------------------------------
263 String SvxHyphenWordDialog::EraseUnusableHyphens_Impl(
264 Reference< XPossibleHyphens > &rxPossHyph,
265 sal_uInt16 _nMaxHyphenationPos )
267 // returns a String showing only those hyphen positions which will result
268 // in a line break if hyphenation is done there
270 String aTxt;
271 DBG_ASSERT(rxPossHyph.is(), "missing possible hyphens");
272 if (rxPossHyph.is())
274 aTxt = String( rxPossHyph->getPossibleHyphens() );
276 Sequence< sal_Int16 > aHyphenationPositions(
277 rxPossHyph->getHyphenationPositions() );
278 sal_Int32 nLen = aHyphenationPositions.getLength();
279 const sal_Int16 *pHyphenationPos = aHyphenationPositions.getConstArray();
281 // find position nIdx after which all hyphen positions are unusable
282 xub_StrLen nIdx = STRING_NOTFOUND,
283 nPos;
284 if (nLen)
286 xub_StrLen nStart = 0;
287 for (sal_Int32 i = 0; i < nLen; ++i)
289 if (pHyphenationPos[i] > _nMaxHyphenationPos)
290 break;
291 else
293 // find corresponding hyphen pos in string
294 nPos = aTxt.Search( sal_Unicode( SW_SOFT_HYPHEN ), nStart );
296 if (nStart == STRING_NOTFOUND)
297 break;
298 else
300 nIdx = nPos;
301 nStart = nPos + 1;
306 DBG_ASSERT(nIdx != STRING_NOTFOUND, "no usable hyphenation position");
308 // remove not usable hyphens from string
309 nPos = nIdx == STRING_NOTFOUND ? 0 : nIdx + 1;
310 String aTmp( sal_Unicode( SW_SOFT_HYPHEN ) ),
311 aEmpty;
312 while (nPos != STRING_NOTFOUND)
313 nPos = aTxt.SearchAndReplace( aTmp, aEmpty, nPos + 1 );
315 return aTxt;
318 // -----------------------------------------------------------------------
320 void SvxHyphenWordDialog::InitControls_Impl()
322 String aTxt;
323 xPossHyph = NULL;
324 if (xHyphenator.is())
326 lang::Locale aLocale( SvxCreateLocale(nActLanguage) );
327 xPossHyph = xHyphenator->createPossibleHyphens( aActWord, aLocale,
328 Sequence< PropertyValue >() );
329 if (xPossHyph.is())
331 aTxt = EraseUnusableHyphens_Impl( xPossHyph, nMaxHyphenationPos );
333 SetLabel_Impl( nActLanguage );
335 aWordEdit.SetText( aTxt );
337 nOldPos = aTxt.Len();
338 SelLeft();
339 EnableLRBtn_Impl();
342 // -----------------------------------------------------------------------
344 void SvxHyphenWordDialog::ContinueHyph_Impl( sal_uInt16 nInsPos )
346 if ( nInsPos != CONTINUE_HYPH && xPossHyph.is())
348 if (nInsPos)
350 //String aTmp( U2S( xPossHyph->getPossibleHyphens() ) );
351 String aTmp( aWordEdit.GetText() );
352 DBG_ASSERT(nInsPos <= aTmp.Len() - 2, "wrong hyphen position");
354 sal_uInt16 nIdxPos = 0;
355 sal_uInt16 i = 0;
356 sal_Unicode c;
357 while (i < aTmp.Len() && HYPHHERE != (c = aTmp.GetChar(i++)) )
359 if (SW_SOFT_HYPHEN == c)
360 nIdxPos++;
363 Sequence< sal_Int16 > aSeq = xPossHyph->getHyphenationPositions();
364 sal_Int32 nLen = aSeq.getLength();
365 DBG_ASSERT(nLen, "empty sequence");
366 DBG_ASSERT(nIdxPos < nLen, "index out of range");
367 if (nLen && nIdxPos < nLen)
369 nInsPos = aSeq.getConstArray()[ nIdxPos ];
370 pHyphWrapper->InsertHyphen( nInsPos );
373 else
375 //! calling with 0 as argument will remove hyphens!
376 pHyphWrapper->InsertHyphen( nInsPos );
380 if ( pHyphWrapper->FindSpellError() )
382 Reference< XHyphenatedWord > xHyphWord( pHyphWrapper->GetLast(), UNO_QUERY );
384 // adapt actual word and language to new found hyphenation result
385 if(xHyphWord.is())
387 aActWord = String( xHyphWord->getWord() );
388 nActLanguage = SvxLocaleToLanguage( xHyphWord->getLocale() );
389 nMaxHyphenationPos = xHyphWord->getHyphenationPos();
390 InitControls_Impl();
393 else
394 EndDialog( RET_OK );
397 // -----------------------------------------------------------------------
399 sal_uInt16 SvxHyphenWordDialog::GetHyphIndex_Impl()
401 sal_uInt16 nPos = 0;
402 String aTxt(aWordEdit.GetText());
404 for ( sal_uInt16 i=0 ; i < aTxt.Len(); ++i )
406 sal_Unicode nChar = aTxt.GetChar( i );
408 if ( nChar == HYPHHERE )
409 break;
411 if ( nChar != SW_SOFT_HYPHEN )
412 nPos++;
414 return nPos;
417 // -----------------------------------------------------------------------
419 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, CutHdl_Impl, Button *, EMPTYARG )
421 if( !bBusy )
423 bBusy = sal_True;
424 ContinueHyph_Impl( nHyphPos );
425 bBusy = sal_False;
427 return 0;
429 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, CutHdl_Impl, Button *, EMPTYARG )
431 // -----------------------------------------------------------------------
433 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, DeleteHdl_Impl, Button *, EMPTYARG )
435 if( !bBusy )
437 bBusy = sal_True;
438 ContinueHyph_Impl();
439 bBusy = sal_False;
441 return 0;
443 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, DeleteHdl_Impl, Button *, EMPTYARG )
445 // -----------------------------------------------------------------------
447 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, ContinueHdl_Impl, Button *, EMPTYARG )
449 if( !bBusy )
451 bBusy = sal_True;
452 ContinueHyph_Impl( CONTINUE_HYPH );
453 bBusy = sal_False;
455 return 0;
457 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, ContinueHdl_Impl, Button *, EMPTYARG )
459 // -----------------------------------------------------------------------
461 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, CancelHdl_Impl, Button *, EMPTYARG )
463 if( !bBusy )
465 bBusy = sal_True;
466 pHyphWrapper->SpellEnd();
467 EndDialog( RET_CANCEL );
468 bBusy = sal_False;
470 return 0;
472 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, CancelHdl_Impl, Button *, EMPTYARG )
474 // -----------------------------------------------------------------------
476 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, Left_Impl, Button *, EMPTYARG )
478 if( !bBusy )
480 bBusy = sal_True;
481 SelLeft();
482 bBusy = sal_False;
484 return 0;
486 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, Left_Impl, Button *, EMPTYARG )
488 // -----------------------------------------------------------------------
490 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, Right_Impl, Button *, EMPTYARG )
492 if( !bBusy )
494 bBusy = sal_True;
495 SelRight();
496 bBusy = sal_False;
498 return 0;
500 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, Right_Impl, Button *, EMPTYARG )
502 // -----------------------------------------------------------------------
504 IMPL_LINK_INLINE_START( SvxHyphenWordDialog, GetFocusHdl_Impl, Edit *, EMPTYARG )
506 aWordEdit.SetSelection( Selection( nOldPos, nOldPos + 1 ) );
507 return 0;
509 IMPL_LINK_INLINE_END( SvxHyphenWordDialog, GetFocusHdl_Impl, Edit *, EMPTYARG )
511 // -----------------------------------------------------------------------
513 IMPL_LINK( SvxHyphenWordDialog, LangError_Impl, void *, nLang )
515 // Status anzeigen
516 String aErr( ::GetLanguageString( (LanguageType)(sal_IntPtr)nLang ) );
517 aErr += SVX_RESSTR( RID_SVXSTR_HMERR_CHECKINSTALL );
518 InfoBox( this, aErr ).Execute();
519 return 0;