xref: /aoo41x/main/cui/source/dialogs/hyphen.cxx (revision 79aad27f)
1*2ee96f1cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2ee96f1cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2ee96f1cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2ee96f1cSAndrew Rist  * distributed with this work for additional information
6*2ee96f1cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2ee96f1cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2ee96f1cSAndrew Rist  * "License"); you may not use this file except in compliance
9*2ee96f1cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*2ee96f1cSAndrew Rist  *
11*2ee96f1cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*2ee96f1cSAndrew Rist  *
13*2ee96f1cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2ee96f1cSAndrew Rist  * software distributed under the License is distributed on an
15*2ee96f1cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2ee96f1cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*2ee96f1cSAndrew Rist  * specific language governing permissions and limitations
18*2ee96f1cSAndrew Rist  * under the License.
19*2ee96f1cSAndrew Rist  *
20*2ee96f1cSAndrew Rist  *************************************************************/
21*2ee96f1cSAndrew Rist 
22*2ee96f1cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_cui.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "hyphen.hxx"
28cdf0e10cSrcweir #include "hyphen.hrc"
29cdf0e10cSrcweir #include "cuires.hrc"
30cdf0e10cSrcweir #include "dialmgr.hxx"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <editeng/splwrap.hxx>
33cdf0e10cSrcweir #include <editeng/svxenum.hxx>
34cdf0e10cSrcweir #include <editeng/unolingu.hxx>
35cdf0e10cSrcweir #include <svtools/langtab.hxx>
36cdf0e10cSrcweir #include <svx/dialmgr.hxx>
37cdf0e10cSrcweir #include <svx/dlgutil.hxx>
38cdf0e10cSrcweir #include <tools/list.hxx>
39cdf0e10cSrcweir #include <tools/shl.hxx>
40cdf0e10cSrcweir #include <vcl/msgbox.hxx>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include <com/sun/star/linguistic2/XPossibleHyphens.hpp>
43cdf0e10cSrcweir 
44cdf0e10cSrcweir using namespace ::com::sun::star;
45cdf0e10cSrcweir 
46cdf0e10cSrcweir 
47cdf0e10cSrcweir #define HYPH_POS_CHAR       '='
48cdf0e10cSrcweir #define CONTINUE_HYPH       USHRT_MAX
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #define CUR_HYPH_POS_CHAR   '-'
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // class HyphenEdit_Impl -------------------------------------------------------
54cdf0e10cSrcweir 
55cdf0e10cSrcweir class HyphenEdit_Impl : public Edit
56cdf0e10cSrcweir {
57cdf0e10cSrcweir public:
58cdf0e10cSrcweir     HyphenEdit_Impl( Window* pParent, const ResId& rResId );
59cdf0e10cSrcweir 
60cdf0e10cSrcweir protected:
61cdf0e10cSrcweir 	virtual void 	KeyInput( const KeyEvent &rKEvt );
62cdf0e10cSrcweir };
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 
HyphenEdit_Impl(Window * pParent,const ResId & rResId)65cdf0e10cSrcweir HyphenEdit_Impl::HyphenEdit_Impl( Window* pParent, const ResId& rResId ) :
66cdf0e10cSrcweir 	Edit( pParent, rResId )
67cdf0e10cSrcweir {
68cdf0e10cSrcweir }
69cdf0e10cSrcweir 
70cdf0e10cSrcweir 
KeyInput(const KeyEvent & rKEvt)71cdf0e10cSrcweir void HyphenEdit_Impl::KeyInput( const KeyEvent& rKEvt )
72cdf0e10cSrcweir {
73cdf0e10cSrcweir //	sal_uInt16 nMod  = rKEvt.GetKeyCode().GetModifier();
74cdf0e10cSrcweir 	sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
75cdf0e10cSrcweir 
76cdf0e10cSrcweir 	switch ( nCode )
77cdf0e10cSrcweir 	{
78cdf0e10cSrcweir 		case KEY_LEFT:
79cdf0e10cSrcweir 			( (SvxHyphenWordDialog*)GetParent() )->SelLeft();
80cdf0e10cSrcweir 			break;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 		case KEY_RIGHT:
83cdf0e10cSrcweir 			( (SvxHyphenWordDialog*)GetParent() )->SelRight();
84cdf0e10cSrcweir 			break;
85cdf0e10cSrcweir 
86cdf0e10cSrcweir 		case KEY_TAB:
87cdf0e10cSrcweir 		case KEY_ESCAPE:
88cdf0e10cSrcweir 		case KEY_RETURN:
89cdf0e10cSrcweir 			Edit::KeyInput(rKEvt);
90cdf0e10cSrcweir 			break;
91cdf0e10cSrcweir 		default:
92cdf0e10cSrcweir 			Control::KeyInput( rKEvt );	// An den Dialog weiterleiten
93cdf0e10cSrcweir 			break;
94cdf0e10cSrcweir 	}
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir 
98cdf0e10cSrcweir // struct SvxHyphenWordDialog_Impl ---------------------------------------------
99cdf0e10cSrcweir 
100cdf0e10cSrcweir struct SvxHyphenWordDialog_Impl
101cdf0e10cSrcweir {
102cdf0e10cSrcweir     SvxHyphenWordDialog *       m_pDialog;
103cdf0e10cSrcweir //    Window *                    m_pParent;
104cdf0e10cSrcweir 
105cdf0e10cSrcweir     FixedText           aWordFT;
106cdf0e10cSrcweir     HyphenEdit_Impl     aWordEdit;
107cdf0e10cSrcweir     ImageButton         aLeftBtn;
108cdf0e10cSrcweir     ImageButton         aRightBtn;
109cdf0e10cSrcweir     OKButton            aOkBtn;
110cdf0e10cSrcweir     PushButton          aContBtn;
111cdf0e10cSrcweir     PushButton          aDelBtn;
112cdf0e10cSrcweir     FixedLine           aFLBottom;
113cdf0e10cSrcweir     HelpButton          aHelpBtn;
114cdf0e10cSrcweir     PushButton          aHyphAll;
115cdf0e10cSrcweir     CancelButton        aCancelBtn;
116cdf0e10cSrcweir     String              aLabel;
117cdf0e10cSrcweir     SvxSpellWrapper*    pHyphWrapper;
118cdf0e10cSrcweir     uno::Reference< linguistic2::XHyphenator >        xHyphenator;
119cdf0e10cSrcweir     uno::Reference< linguistic2::XPossibleHyphens >   xPossHyph;
120cdf0e10cSrcweir     String              aEditWord;      // aEditWord and aWordEdit.GetText() differ only by the character for the current selected hyphenation position
121cdf0e10cSrcweir     String              aActWord;           // actual word to be hyphenated
122cdf0e10cSrcweir     LanguageType        nActLanguage;       // and its language
123cdf0e10cSrcweir     sal_uInt16          nMaxHyphenationPos; // right most valid hyphenation pos
124cdf0e10cSrcweir     sal_uInt16          nHyphPos;
125cdf0e10cSrcweir     sal_uInt16          nOldPos;
126cdf0e10cSrcweir     sal_Int32           nHyphenationPositionsOffset;
127cdf0e10cSrcweir     sal_Bool            bBusy;
128cdf0e10cSrcweir 
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     void            EnableLRBtn_Impl();
131cdf0e10cSrcweir     String          EraseUnusableHyphens_Impl( ::com::sun::star::uno::Reference< ::com::sun::star::linguistic2::XPossibleHyphens >  &rxPossHyph, sal_uInt16 nMaxHyphenationPos );
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     void            InitControls_Impl();
134cdf0e10cSrcweir     void            ContinueHyph_Impl( sal_uInt16 nInsPos = 0 );
135cdf0e10cSrcweir     sal_uInt16      GetHyphIndex_Impl();
136cdf0e10cSrcweir     void            SelLeft_Impl();
137cdf0e10cSrcweir     void            SelRight_Impl();
138cdf0e10cSrcweir 
139cdf0e10cSrcweir     DECL_LINK( Left_Impl, Button* );
140cdf0e10cSrcweir     DECL_LINK( Right_Impl, Button* );
141cdf0e10cSrcweir     DECL_LINK( CutHdl_Impl, Button* );
142cdf0e10cSrcweir     DECL_LINK( ContinueHdl_Impl, Button* );
143cdf0e10cSrcweir     DECL_LINK( DeleteHdl_Impl, Button* );
144cdf0e10cSrcweir     DECL_LINK( HyphenateAllHdl_Impl, Button* );
145cdf0e10cSrcweir     DECL_LINK( CancelHdl_Impl, Button* );
146cdf0e10cSrcweir     DECL_LINK( GetFocusHdl_Impl, Edit* );
147cdf0e10cSrcweir 
148cdf0e10cSrcweir 
149cdf0e10cSrcweir     SvxHyphenWordDialog_Impl(
150cdf0e10cSrcweir             SvxHyphenWordDialog * pDialog,
151cdf0e10cSrcweir             const String &rWord,
152cdf0e10cSrcweir             LanguageType nLang,
153cdf0e10cSrcweir             uno::Reference< linguistic2::XHyphenator >  &xHyphen,
154cdf0e10cSrcweir             SvxSpellWrapper* pWrapper );
155cdf0e10cSrcweir     ~SvxHyphenWordDialog_Impl();
156cdf0e10cSrcweir };
157cdf0e10cSrcweir 
158cdf0e10cSrcweir 
SvxHyphenWordDialog_Impl(SvxHyphenWordDialog * pDialog,const String & rWord,LanguageType nLang,uno::Reference<linguistic2::XHyphenator> & xHyphen,SvxSpellWrapper * pWrapper)159cdf0e10cSrcweir SvxHyphenWordDialog_Impl::SvxHyphenWordDialog_Impl(
160cdf0e10cSrcweir         SvxHyphenWordDialog * pDialog,
161cdf0e10cSrcweir         const String &rWord,
162cdf0e10cSrcweir         LanguageType nLang,
163cdf0e10cSrcweir         uno::Reference< linguistic2::XHyphenator >  &xHyphen,
164cdf0e10cSrcweir         SvxSpellWrapper* pWrapper ) :
165cdf0e10cSrcweir 
166cdf0e10cSrcweir     m_pDialog   ( pDialog ),
167cdf0e10cSrcweir     aWordFT     ( pDialog, CUI_RES( FT_WORD ) ),
168cdf0e10cSrcweir     aWordEdit   ( pDialog, CUI_RES( ED_WORD ) ),
169cdf0e10cSrcweir     aLeftBtn    ( pDialog, CUI_RES( BTN_LEFT ) ),
170cdf0e10cSrcweir     aRightBtn   ( pDialog, CUI_RES( BTN_RIGHT ) ),
171cdf0e10cSrcweir     aOkBtn      ( pDialog, CUI_RES( BTN_HYPH_CUT ) ),
172cdf0e10cSrcweir     aContBtn    ( pDialog, CUI_RES( BTN_HYPH_CONTINUE ) ),
173cdf0e10cSrcweir     aDelBtn     ( pDialog, CUI_RES( BTN_HYPH_DELETE ) ),
174cdf0e10cSrcweir     aFLBottom   ( pDialog, CUI_RES( FL_BOTTOM ) ),
175cdf0e10cSrcweir     aHelpBtn    ( pDialog, CUI_RES( BTN_HYPH_HELP ) ),
176cdf0e10cSrcweir     aHyphAll    ( pDialog, CUI_RES( BTN_HYPH_ALL ) ),
177cdf0e10cSrcweir     aCancelBtn  ( pDialog, CUI_RES( BTN_HYPH_CANCEL ) ),
178cdf0e10cSrcweir     aLabel          ( pDialog->GetText() ),
179cdf0e10cSrcweir     pHyphWrapper    ( NULL ),
180cdf0e10cSrcweir     xHyphenator     ( NULL ),
181cdf0e10cSrcweir     xPossHyph       ( NULL ),
182cdf0e10cSrcweir     aActWord        (  ),
183cdf0e10cSrcweir     nActLanguage    ( LANGUAGE_NONE ),
184cdf0e10cSrcweir     nMaxHyphenationPos  ( 0 ),
185cdf0e10cSrcweir     nHyphPos        ( 0 ),
186cdf0e10cSrcweir     nOldPos         ( 0 ),
187cdf0e10cSrcweir     nHyphenationPositionsOffset( 0 ),
188cdf0e10cSrcweir     bBusy           ( sal_False )
189cdf0e10cSrcweir {
190cdf0e10cSrcweir     aActWord       = rWord;
191cdf0e10cSrcweir     nActLanguage   = nLang;
192cdf0e10cSrcweir     xHyphenator    = xHyphen;
193cdf0e10cSrcweir     pHyphWrapper   = pWrapper;
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     uno::Reference< linguistic2::XHyphenatedWord >  xHyphWord( pHyphWrapper ?
196cdf0e10cSrcweir             pHyphWrapper->GetLast() : NULL, uno::UNO_QUERY );
197cdf0e10cSrcweir     DBG_ASSERT( xHyphWord.is(), "hyphenation result missing" );
198cdf0e10cSrcweir     if (xHyphWord.is())
199cdf0e10cSrcweir     {
200cdf0e10cSrcweir         DBG_ASSERT( aActWord == String( xHyphWord->getWord() ), "word mismatch" );
201cdf0e10cSrcweir         DBG_ASSERT( nActLanguage == SvxLocaleToLanguage( xHyphWord->getLocale() ), "language mismatch" );
202cdf0e10cSrcweir         nMaxHyphenationPos = xHyphWord->getHyphenationPos();
203cdf0e10cSrcweir     }
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     InitControls_Impl();
206cdf0e10cSrcweir     aWordEdit.GrabFocus();
207cdf0e10cSrcweir 
208cdf0e10cSrcweir     aLeftBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, Left_Impl ) );
209cdf0e10cSrcweir     aRightBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, Right_Impl ) );
210cdf0e10cSrcweir     aOkBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, CutHdl_Impl ) );
211cdf0e10cSrcweir     aContBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, ContinueHdl_Impl ) );
212cdf0e10cSrcweir     aDelBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, DeleteHdl_Impl ) );
213cdf0e10cSrcweir     aHyphAll.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, HyphenateAllHdl_Impl ) );
214cdf0e10cSrcweir     aCancelBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog_Impl, CancelHdl_Impl ) );
215cdf0e10cSrcweir     aWordEdit.SetGetFocusHdl( LINK( this, SvxHyphenWordDialog_Impl, GetFocusHdl_Impl ) );
216cdf0e10cSrcweir }
217cdf0e10cSrcweir 
218cdf0e10cSrcweir 
~SvxHyphenWordDialog_Impl()219cdf0e10cSrcweir SvxHyphenWordDialog_Impl::~SvxHyphenWordDialog_Impl()
220cdf0e10cSrcweir {
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 
EnableLRBtn_Impl()224cdf0e10cSrcweir void SvxHyphenWordDialog_Impl::EnableLRBtn_Impl()
225cdf0e10cSrcweir {
226cdf0e10cSrcweir     String  aTxt( aEditWord );
227cdf0e10cSrcweir     xub_StrLen nLen = aTxt.Len();
228cdf0e10cSrcweir     xub_StrLen i;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir     aRightBtn.Disable();
231cdf0e10cSrcweir     for ( i = nOldPos + 2; i < nLen; ++i )
232cdf0e10cSrcweir     {
233cdf0e10cSrcweir         if ( aTxt.GetChar( i ) == sal_Unicode( HYPH_POS_CHAR ) )
234cdf0e10cSrcweir         {
235cdf0e10cSrcweir             aRightBtn.Enable();
236cdf0e10cSrcweir             break;
237cdf0e10cSrcweir         }
238cdf0e10cSrcweir     }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir     DBG_ASSERT(nOldPos < aTxt.Len(), "nOldPos out of range");
241cdf0e10cSrcweir     if (nOldPos >= aTxt.Len())
242cdf0e10cSrcweir         nOldPos = aTxt.Len() - 1;
243cdf0e10cSrcweir     aLeftBtn.Disable();
244cdf0e10cSrcweir     for ( i = nOldPos;  i-- > 0; )
245cdf0e10cSrcweir     {
246cdf0e10cSrcweir         if ( aTxt.GetChar( i ) == sal_Unicode( HYPH_POS_CHAR ) )
247cdf0e10cSrcweir         {
248cdf0e10cSrcweir             aLeftBtn.Enable();
249cdf0e10cSrcweir             break;
250cdf0e10cSrcweir         }
251cdf0e10cSrcweir     }
252cdf0e10cSrcweir }
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 
EraseUnusableHyphens_Impl(uno::Reference<linguistic2::XPossibleHyphens> & rxPossHyph,sal_uInt16 _nMaxHyphenationPos)255cdf0e10cSrcweir String SvxHyphenWordDialog_Impl::EraseUnusableHyphens_Impl(
256cdf0e10cSrcweir         uno::Reference< linguistic2::XPossibleHyphens >  &rxPossHyph,
257cdf0e10cSrcweir         sal_uInt16 _nMaxHyphenationPos )
258cdf0e10cSrcweir {
259cdf0e10cSrcweir     // returns a String showing only those hyphen positions which will result
260cdf0e10cSrcweir     // in a line break if hyphenation is done there
261cdf0e10cSrcweir     // 1) we will need to discard all hyphenation positions at th end that
262cdf0e10cSrcweir     // will not result in a line break where the text to the left still fits
263cdf0e10cSrcweir     // on the line.
264cdf0e10cSrcweir     // 2) since as from OOo 3.2 '-' are part of a word an thus text like
265cdf0e10cSrcweir     // 'multi-line-editor' is regarded as single word we also need to discard those
266cdf0e10cSrcweir     // hyphenation positions to the left of the rightmost '-' that is still left of
267cdf0e10cSrcweir     // the rightmost valid hyphenation position according to 1)
268cdf0e10cSrcweir     //
269cdf0e10cSrcweir     // Example:
270cdf0e10cSrcweir     // If the possible hyphenation position in 'multi-line-editor' are to eb marked
271cdf0e10cSrcweir     // by '=' then the text will look like this 'mul=ti-line-ed=it=or'.
272cdf0e10cSrcweir     // If now the first line is only large enough for 'multi-line-edi' we need to discard
273cdf0e10cSrcweir     // the last possible hyphnation point because of 1). The the right most valid
274cdf0e10cSrcweir     // hyphenation position is "ed=itor". The first '-' left of this position is
275cdf0e10cSrcweir     // "line-ed", thus because of 2) we now need to discard all possible hyphneation
276cdf0e10cSrcweir     // positions to the left of that as well. Thus in the end leaving us with just
277cdf0e10cSrcweir     // 'multi-line-ed=itor' as return value for this function. (Just one valid hyphenation
278cdf0e10cSrcweir     // position for the user too choose from. However ALL the '-' characters in the word
279cdf0e10cSrcweir     // will ALWAYS be valid implicit hyphenation positions for the core to choose from!
280cdf0e10cSrcweir     // And thus even if this word is skipped in the hyphenation dialog it will still be broken
281cdf0e10cSrcweir     // right after 'multi-line-' (actually it might already be broken up that way before
282cdf0e10cSrcweir     // the hyphenation dialog is called!).
283cdf0e10cSrcweir     // Thus rule 2) just eliminates those positions which will not be used by the core at all
284cdf0e10cSrcweir     // even if the user were to select one of them.
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     String aTxt;
287cdf0e10cSrcweir     DBG_ASSERT(rxPossHyph.is(), "missing possible hyphens");
288cdf0e10cSrcweir     if (rxPossHyph.is())
289cdf0e10cSrcweir     {
290cdf0e10cSrcweir         DBG_ASSERT( aActWord == String( rxPossHyph->getWord() ), "word mismatch"  );
291cdf0e10cSrcweir 
292cdf0e10cSrcweir         aTxt = String( rxPossHyph->getPossibleHyphens() );
293cdf0e10cSrcweir 
294cdf0e10cSrcweir         nHyphenationPositionsOffset = 0;
295cdf0e10cSrcweir         uno::Sequence< sal_Int16 > aHyphenationPositions(
296cdf0e10cSrcweir                 rxPossHyph->getHyphenationPositions() );
297cdf0e10cSrcweir         sal_Int32 nLen = aHyphenationPositions.getLength();
298cdf0e10cSrcweir         const sal_Int16 *pHyphenationPos = aHyphenationPositions.getConstArray();
299cdf0e10cSrcweir 
300cdf0e10cSrcweir         // find position nIdx after which all hyphen positions are unusable
301cdf0e10cSrcweir         xub_StrLen  nIdx = STRING_NOTFOUND;
302cdf0e10cSrcweir         xub_StrLen  nPos = 0, nPos1 = 0, nPos2 = 0;
303cdf0e10cSrcweir         if (nLen)
304cdf0e10cSrcweir         {
305cdf0e10cSrcweir             xub_StrLen nStart = 0;
306cdf0e10cSrcweir             for (sal_Int32 i = 0;  i < nLen;  ++i)
307cdf0e10cSrcweir             {
308cdf0e10cSrcweir                 if (pHyphenationPos[i] > _nMaxHyphenationPos)
309cdf0e10cSrcweir                     break;
310cdf0e10cSrcweir                 else
311cdf0e10cSrcweir                 {
312cdf0e10cSrcweir                     // find corresponding hyphen pos in string
313cdf0e10cSrcweir                     nPos = aTxt.Search( sal_Unicode( HYPH_POS_CHAR ), nStart );
314cdf0e10cSrcweir 
315cdf0e10cSrcweir                     if (nStart == STRING_NOTFOUND)
316cdf0e10cSrcweir                         break;
317cdf0e10cSrcweir                     else
318cdf0e10cSrcweir                     {
319cdf0e10cSrcweir                         nIdx = nPos;
320cdf0e10cSrcweir                         nStart = nPos + 1;
321cdf0e10cSrcweir                     }
322cdf0e10cSrcweir                 }
323cdf0e10cSrcweir             }
324cdf0e10cSrcweir         }
325cdf0e10cSrcweir         DBG_ASSERT(nIdx != STRING_NOTFOUND, "no usable hyphenation position");
326cdf0e10cSrcweir 
327cdf0e10cSrcweir         // 1) remove all not usable hyphenation positions from the end of the string
328cdf0e10cSrcweir         nPos = nIdx == STRING_NOTFOUND ? 0 : nIdx + 1;
329cdf0e10cSrcweir         nPos1 = nPos;   //save for later use in 2) below
330cdf0e10cSrcweir         const String aTmp( sal_Unicode( HYPH_POS_CHAR ) );
331cdf0e10cSrcweir         const String aEmpty;
332cdf0e10cSrcweir         while (nPos != STRING_NOTFOUND)
333cdf0e10cSrcweir             nPos = aTxt.SearchAndReplace( aTmp, aEmpty, nPos + 1 );
334cdf0e10cSrcweir 
335cdf0e10cSrcweir         // 2) remove all hyphenation positions from the start that are not considered by the core
336cdf0e10cSrcweir         const String aSearchRange( aTxt.Copy( 0, nPos1 ) );
337cdf0e10cSrcweir         nPos2 = aSearchRange.SearchBackward( '-' );  // the '-' position the core will use by default
338cdf0e10cSrcweir         if (nPos2 != STRING_NOTFOUND)
339cdf0e10cSrcweir         {
340cdf0e10cSrcweir             String aLeft( aSearchRange.Copy( 0, nPos2 ) );
341cdf0e10cSrcweir             nPos = 0;
342cdf0e10cSrcweir             while (nPos != STRING_NOTFOUND)
343cdf0e10cSrcweir             {
344cdf0e10cSrcweir                 nPos = aLeft.SearchAndReplace( aTmp, aEmpty, nPos + 1 );
345cdf0e10cSrcweir                 if (nPos != STRING_NOTFOUND)
346cdf0e10cSrcweir                     ++nHyphenationPositionsOffset;
347cdf0e10cSrcweir             }
348cdf0e10cSrcweir             aTxt.Replace( 0, nPos2, aLeft );
349cdf0e10cSrcweir         }
350cdf0e10cSrcweir     }
351cdf0e10cSrcweir     return aTxt;
352cdf0e10cSrcweir }
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 
InitControls_Impl()355cdf0e10cSrcweir void SvxHyphenWordDialog_Impl::InitControls_Impl()
356cdf0e10cSrcweir {
357cdf0e10cSrcweir     xPossHyph = NULL;
358cdf0e10cSrcweir     if (xHyphenator.is())
359cdf0e10cSrcweir     {
360cdf0e10cSrcweir         lang::Locale aLocale( SvxCreateLocale(nActLanguage) );
361cdf0e10cSrcweir         xPossHyph = xHyphenator->createPossibleHyphens( aActWord, aLocale,
362cdf0e10cSrcweir                                                         uno::Sequence< beans::PropertyValue >() );
363cdf0e10cSrcweir         if (xPossHyph.is())
364cdf0e10cSrcweir             aEditWord = EraseUnusableHyphens_Impl( xPossHyph, nMaxHyphenationPos );
365cdf0e10cSrcweir     }
366cdf0e10cSrcweir     aWordEdit.SetText( aEditWord );
367cdf0e10cSrcweir 
368cdf0e10cSrcweir     nOldPos = aEditWord.Len();
369cdf0e10cSrcweir     SelLeft_Impl();
370cdf0e10cSrcweir     EnableLRBtn_Impl();
371cdf0e10cSrcweir }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir 
ContinueHyph_Impl(sal_uInt16 nInsPos)374cdf0e10cSrcweir void SvxHyphenWordDialog_Impl::ContinueHyph_Impl( sal_uInt16 nInsPos )
375cdf0e10cSrcweir {
376cdf0e10cSrcweir     if ( nInsPos != CONTINUE_HYPH  &&  xPossHyph.is())
377cdf0e10cSrcweir     {
378cdf0e10cSrcweir         if (nInsPos)
379cdf0e10cSrcweir         {
380cdf0e10cSrcweir             String aTmp( aEditWord );
381cdf0e10cSrcweir             DBG_ASSERT(nInsPos <= aTmp.Len() - 2, "wrong hyphen position");
382cdf0e10cSrcweir 
383cdf0e10cSrcweir             sal_Int16 nIdxPos = -1;
384cdf0e10cSrcweir             for (sal_uInt16 i = 0; i <= nInsPos; ++i)
385cdf0e10cSrcweir             {
386cdf0e10cSrcweir                 if (HYPH_POS_CHAR == aTmp.GetChar( i ))
387cdf0e10cSrcweir                     nIdxPos++;
388cdf0e10cSrcweir             }
389cdf0e10cSrcweir             // take the possible hyphenation positions that got removed from the
390cdf0e10cSrcweir             // start of the wor dinot account:
391cdf0e10cSrcweir             nIdxPos += nHyphenationPositionsOffset;
392cdf0e10cSrcweir 
393cdf0e10cSrcweir             uno::Sequence< sal_Int16 > aSeq = xPossHyph->getHyphenationPositions();
394cdf0e10cSrcweir             sal_Int32 nLen = aSeq.getLength();
395cdf0e10cSrcweir             DBG_ASSERT(nLen, "empty sequence");
396cdf0e10cSrcweir             DBG_ASSERT(0 <= nIdxPos && nIdxPos < nLen, "index out of range");
397cdf0e10cSrcweir             if (nLen && 0 <= nIdxPos && nIdxPos < nLen)
398cdf0e10cSrcweir             {
399cdf0e10cSrcweir                 nInsPos = aSeq.getConstArray()[ nIdxPos ];
400cdf0e10cSrcweir                 pHyphWrapper->InsertHyphen( nInsPos );
401cdf0e10cSrcweir             }
402cdf0e10cSrcweir         }
403cdf0e10cSrcweir         else
404cdf0e10cSrcweir         {
405cdf0e10cSrcweir             //! calling with 0 as argument will remove hyphens!
406cdf0e10cSrcweir             pHyphWrapper->InsertHyphen( nInsPos );
407cdf0e10cSrcweir         }
408cdf0e10cSrcweir     }
409cdf0e10cSrcweir 
410cdf0e10cSrcweir     if ( pHyphWrapper->FindSpellError() )
411cdf0e10cSrcweir     {
412cdf0e10cSrcweir         uno::Reference< linguistic2::XHyphenatedWord >  xHyphWord( pHyphWrapper->GetLast(), uno::UNO_QUERY );
413cdf0e10cSrcweir 
414cdf0e10cSrcweir         // adapt actual word and language to new found hyphenation result
415cdf0e10cSrcweir         if(xHyphWord.is())
416cdf0e10cSrcweir         {
417cdf0e10cSrcweir             aActWord    = String( xHyphWord->getWord() );
418cdf0e10cSrcweir             nActLanguage = SvxLocaleToLanguage( xHyphWord->getLocale() );
419cdf0e10cSrcweir             nMaxHyphenationPos = xHyphWord->getHyphenationPos();
420cdf0e10cSrcweir             InitControls_Impl();
421cdf0e10cSrcweir             m_pDialog->SetWindowTitle( nActLanguage );
422cdf0e10cSrcweir         }
423cdf0e10cSrcweir     }
424cdf0e10cSrcweir     else
425cdf0e10cSrcweir         m_pDialog->EndDialog( RET_OK );
426cdf0e10cSrcweir }
427cdf0e10cSrcweir 
428cdf0e10cSrcweir 
GetHyphIndex_Impl()429cdf0e10cSrcweir sal_uInt16 SvxHyphenWordDialog_Impl::GetHyphIndex_Impl()
430cdf0e10cSrcweir {
431cdf0e10cSrcweir     sal_uInt16 nPos = 0;
432cdf0e10cSrcweir     String aTxt( aWordEdit.GetText() );
433cdf0e10cSrcweir 
434cdf0e10cSrcweir     for ( sal_uInt16 i=0 ; i < aTxt.Len(); ++i )
435cdf0e10cSrcweir     {
436cdf0e10cSrcweir         sal_Unicode cChar = aTxt.GetChar( i );
437cdf0e10cSrcweir         if ( cChar == CUR_HYPH_POS_CHAR )
438cdf0e10cSrcweir             break;
439cdf0e10cSrcweir         if ( cChar != HYPH_POS_CHAR )
440cdf0e10cSrcweir             nPos++;
441cdf0e10cSrcweir     }
442cdf0e10cSrcweir     return nPos;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir 
SelLeft_Impl()446cdf0e10cSrcweir void SvxHyphenWordDialog_Impl::SelLeft_Impl()
447cdf0e10cSrcweir {
448cdf0e10cSrcweir     DBG_ASSERT( nOldPos > 0, "invalid hyphenation position" );
449cdf0e10cSrcweir     if (nOldPos > 0)
450cdf0e10cSrcweir     {
451cdf0e10cSrcweir         String aTxt( aEditWord );
452cdf0e10cSrcweir         for ( xub_StrLen i = nOldPos - 1;  i > 0; --i)
453cdf0e10cSrcweir         {
454cdf0e10cSrcweir             DBG_ASSERT(i <= aTxt.Len(), "index out of range");
455cdf0e10cSrcweir             if (aTxt.GetChar( i ) == sal_Unicode( HYPH_POS_CHAR ))
456cdf0e10cSrcweir             {
457cdf0e10cSrcweir                 aTxt.SetChar( i, sal_Unicode( CUR_HYPH_POS_CHAR ) );
458cdf0e10cSrcweir 
459cdf0e10cSrcweir                 nOldPos = i;
460cdf0e10cSrcweir                 aWordEdit.SetText( aTxt );
461cdf0e10cSrcweir                 aWordEdit.GrabFocus();
462cdf0e10cSrcweir                 aWordEdit.SetSelection( Selection( i, i + 1 ) );
463cdf0e10cSrcweir                 break;
464cdf0e10cSrcweir             }
465cdf0e10cSrcweir         }
466cdf0e10cSrcweir         nHyphPos = GetHyphIndex_Impl();
467cdf0e10cSrcweir         EnableLRBtn_Impl();
468cdf0e10cSrcweir     }
469cdf0e10cSrcweir }
470cdf0e10cSrcweir 
471cdf0e10cSrcweir 
SelRight_Impl()472cdf0e10cSrcweir void SvxHyphenWordDialog_Impl::SelRight_Impl()
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     String aTxt( aEditWord );
475cdf0e10cSrcweir     for ( xub_StrLen i = nOldPos + 1;  i < aTxt.Len();  ++i )
476cdf0e10cSrcweir     {
477cdf0e10cSrcweir         if (aTxt.GetChar( i ) == sal_Unicode( HYPH_POS_CHAR ))
478cdf0e10cSrcweir         {
479cdf0e10cSrcweir             aTxt.SetChar( i, sal_Unicode( CUR_HYPH_POS_CHAR ) );
480cdf0e10cSrcweir 
481cdf0e10cSrcweir             nOldPos = i;
482cdf0e10cSrcweir             aWordEdit.SetText( aTxt );
483cdf0e10cSrcweir             aWordEdit.GrabFocus();
484cdf0e10cSrcweir             aWordEdit.SetSelection( Selection( i, i + 1 ) );
485cdf0e10cSrcweir             break;
486cdf0e10cSrcweir         }
487cdf0e10cSrcweir     }
488cdf0e10cSrcweir     nHyphPos = GetHyphIndex_Impl();
489cdf0e10cSrcweir     EnableLRBtn_Impl();
490cdf0e10cSrcweir }
491cdf0e10cSrcweir 
492cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,CutHdl_Impl,Button *,EMPTYARG)493cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, CutHdl_Impl, Button *, EMPTYARG )
494cdf0e10cSrcweir {
495cdf0e10cSrcweir     if( !bBusy )
496cdf0e10cSrcweir     {
497cdf0e10cSrcweir         bBusy = sal_True;
498cdf0e10cSrcweir         ContinueHyph_Impl( /*nHyphPos*/nOldPos );
499cdf0e10cSrcweir         bBusy = sal_False;
500cdf0e10cSrcweir     }
501cdf0e10cSrcweir     return 0;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
504cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,HyphenateAllHdl_Impl,Button *,EMPTYARG)505cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, HyphenateAllHdl_Impl, Button *, EMPTYARG /*pButton*/ )
506cdf0e10cSrcweir {
507cdf0e10cSrcweir     if( !bBusy )
508cdf0e10cSrcweir     {
509cdf0e10cSrcweir         try
510cdf0e10cSrcweir         {
511cdf0e10cSrcweir             uno::Reference< beans::XPropertySet >  xProp( SvxGetLinguPropertySet() );
512cdf0e10cSrcweir             const rtl::OUString aName( rtl::OUString::createFromAscii( "IsHyphAuto" ) );
513cdf0e10cSrcweir             uno::Any aAny;
514cdf0e10cSrcweir 
515cdf0e10cSrcweir             aAny <<= sal_True;
516cdf0e10cSrcweir             xProp->setPropertyValue( aName, aAny );
517cdf0e10cSrcweir 
518cdf0e10cSrcweir             bBusy = sal_True;
519cdf0e10cSrcweir             ContinueHyph_Impl( /*nHyphPos*/nOldPos );
520cdf0e10cSrcweir             bBusy = sal_False;
521cdf0e10cSrcweir 
522cdf0e10cSrcweir             aAny <<= sal_False;
523cdf0e10cSrcweir             xProp->setPropertyValue( aName, aAny );
524cdf0e10cSrcweir         }
525cdf0e10cSrcweir         catch (uno::Exception &e)
526cdf0e10cSrcweir         {
527cdf0e10cSrcweir             (void) e;
528cdf0e10cSrcweir             DBG_ASSERT( 0, "Hyphenate All failed" );
529cdf0e10cSrcweir         }
530cdf0e10cSrcweir     }
531cdf0e10cSrcweir     return 0;
532cdf0e10cSrcweir }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,DeleteHdl_Impl,Button *,EMPTYARG)535cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, DeleteHdl_Impl, Button *, EMPTYARG )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir     if( !bBusy )
538cdf0e10cSrcweir     {
539cdf0e10cSrcweir         bBusy = sal_True;
540cdf0e10cSrcweir         ContinueHyph_Impl();
541cdf0e10cSrcweir         bBusy = sal_False;
542cdf0e10cSrcweir     }
543cdf0e10cSrcweir     return 0;
544cdf0e10cSrcweir }
545cdf0e10cSrcweir 
546cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,ContinueHdl_Impl,Button *,EMPTYARG)547cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, ContinueHdl_Impl, Button *, EMPTYARG )
548cdf0e10cSrcweir {
549cdf0e10cSrcweir     if( !bBusy )
550cdf0e10cSrcweir     {
551cdf0e10cSrcweir         bBusy = sal_True;
552cdf0e10cSrcweir         ContinueHyph_Impl( CONTINUE_HYPH );
553cdf0e10cSrcweir         bBusy = sal_False;
554cdf0e10cSrcweir     }
555cdf0e10cSrcweir     return 0;
556cdf0e10cSrcweir }
557cdf0e10cSrcweir 
558cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,CancelHdl_Impl,Button *,EMPTYARG)559cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, CancelHdl_Impl, Button *, EMPTYARG )
560cdf0e10cSrcweir {
561cdf0e10cSrcweir     if( !bBusy )
562cdf0e10cSrcweir     {
563cdf0e10cSrcweir         bBusy = sal_True;
564cdf0e10cSrcweir         pHyphWrapper->SpellEnd();
565cdf0e10cSrcweir         m_pDialog->EndDialog( RET_CANCEL );
566cdf0e10cSrcweir         bBusy = sal_False;
567cdf0e10cSrcweir     }
568cdf0e10cSrcweir     return 0;
569cdf0e10cSrcweir }
570cdf0e10cSrcweir 
571cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,Left_Impl,Button *,EMPTYARG)572cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, Left_Impl, Button *, EMPTYARG )
573cdf0e10cSrcweir {
574cdf0e10cSrcweir     if( !bBusy )
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir         bBusy = sal_True;
577cdf0e10cSrcweir         SelLeft_Impl();
578cdf0e10cSrcweir         bBusy = sal_False;
579cdf0e10cSrcweir     }
580cdf0e10cSrcweir     return 0;
581cdf0e10cSrcweir }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,Right_Impl,Button *,EMPTYARG)584cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, Right_Impl, Button *, EMPTYARG )
585cdf0e10cSrcweir {
586cdf0e10cSrcweir     if( !bBusy )
587cdf0e10cSrcweir     {
588cdf0e10cSrcweir         bBusy = sal_True;
589cdf0e10cSrcweir         SelRight_Impl();
590cdf0e10cSrcweir         bBusy = sal_False;
591cdf0e10cSrcweir     }
592cdf0e10cSrcweir     return 0;
593cdf0e10cSrcweir }
594cdf0e10cSrcweir 
595cdf0e10cSrcweir 
IMPL_LINK(SvxHyphenWordDialog_Impl,GetFocusHdl_Impl,Edit *,EMPTYARG)596cdf0e10cSrcweir IMPL_LINK( SvxHyphenWordDialog_Impl, GetFocusHdl_Impl, Edit *, EMPTYARG )
597cdf0e10cSrcweir {
598cdf0e10cSrcweir     aWordEdit.SetSelection( Selection( nOldPos, nOldPos + 1 ) );
599cdf0e10cSrcweir     return 0;
600cdf0e10cSrcweir }
601cdf0e10cSrcweir 
602cdf0e10cSrcweir 
603cdf0e10cSrcweir // class SvxHyphenWordDialog ---------------------------------------------
604cdf0e10cSrcweir 
SvxHyphenWordDialog(const String & rWord,LanguageType nLang,Window * pParent,uno::Reference<linguistic2::XHyphenator> & xHyphen,SvxSpellWrapper * pWrapper)605cdf0e10cSrcweir SvxHyphenWordDialog::SvxHyphenWordDialog(
606cdf0e10cSrcweir     const String &rWord, LanguageType nLang,
607cdf0e10cSrcweir     Window* pParent,
608cdf0e10cSrcweir     uno::Reference< linguistic2::XHyphenator >  &xHyphen,
609cdf0e10cSrcweir     SvxSpellWrapper* pWrapper ) :
610cdf0e10cSrcweir 
611cdf0e10cSrcweir     SfxModalDialog( pParent, CUI_RES( RID_SVXDLG_HYPHENATE ) )
612cdf0e10cSrcweir {
613cdf0e10cSrcweir     m_pImpl = std::auto_ptr< SvxHyphenWordDialog_Impl >(
614cdf0e10cSrcweir             new SvxHyphenWordDialog_Impl( this, rWord, nLang, xHyphen, pWrapper ) );
615cdf0e10cSrcweir 
616cdf0e10cSrcweir     FreeResource();
617cdf0e10cSrcweir 
618cdf0e10cSrcweir     SetWindowTitle( nLang );
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 	// disable controls if service is not available
621cdf0e10cSrcweir     if (!m_pImpl->xHyphenator.is())
622cdf0e10cSrcweir 		Enable( sal_False );
623cdf0e10cSrcweir }
624cdf0e10cSrcweir 
625cdf0e10cSrcweir 
~SvxHyphenWordDialog()626cdf0e10cSrcweir SvxHyphenWordDialog::~SvxHyphenWordDialog()
627cdf0e10cSrcweir {
628cdf0e10cSrcweir }
629cdf0e10cSrcweir 
630cdf0e10cSrcweir 
SetWindowTitle(LanguageType nLang)631cdf0e10cSrcweir void SvxHyphenWordDialog::SetWindowTitle( LanguageType nLang )
632cdf0e10cSrcweir {
633cdf0e10cSrcweir     String aLangStr( SvtLanguageTable::GetLanguageString( nLang ) );
634cdf0e10cSrcweir     String aTmp( m_pImpl->aLabel );
635cdf0e10cSrcweir     aTmp.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
636cdf0e10cSrcweir     aTmp.Append( aLangStr );
637cdf0e10cSrcweir     aTmp.Append( sal_Unicode( ')' ) );
638cdf0e10cSrcweir     SetText( aTmp );
639cdf0e10cSrcweir }
640cdf0e10cSrcweir 
641cdf0e10cSrcweir 
SelLeft()642cdf0e10cSrcweir void SvxHyphenWordDialog::SelLeft()
643cdf0e10cSrcweir {
644cdf0e10cSrcweir     m_pImpl->SelRight_Impl();
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir 
SelRight()648cdf0e10cSrcweir void SvxHyphenWordDialog::SelRight()
649cdf0e10cSrcweir {
650cdf0e10cSrcweir     m_pImpl->SelLeft_Impl();
651cdf0e10cSrcweir }
652cdf0e10cSrcweir 
653cdf0e10cSrcweir 
654