551 lines
16 KiB
C++
551 lines
16 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: hyphen.cxx,v $
|
|
*
|
|
* $Revision: 1.8 $
|
|
*
|
|
* last change: $Author: obo $ $Date: 2006-10-12 12:15:24 $
|
|
*
|
|
* The Contents of this file are made available subject to
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
|
*
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_svx.hxx"
|
|
|
|
// include ---------------------------------------------------------------
|
|
|
|
#ifndef _SHL_HXX
|
|
#include <tools/shl.hxx>
|
|
#endif
|
|
|
|
#ifndef _LIST_HXX
|
|
#include <tools/list.hxx>
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_LINGUISTIC2_XPOSSIBLEHYPHENS_HPP_
|
|
#include <com/sun/star/linguistic2/XPossibleHyphens.hpp>
|
|
#endif
|
|
|
|
#ifndef _SV_MSGBOX_HXX
|
|
#include <vcl/msgbox.hxx>
|
|
#endif
|
|
|
|
|
|
#define _SVX_HYPHEN_CXX
|
|
|
|
#include "dialogs.hrc"
|
|
#include "hyphen.hrc"
|
|
|
|
#include "svxenum.hxx"
|
|
#include "hyphen.hxx"
|
|
#include "splwrap.hxx"
|
|
#include "dlgutil.hxx"
|
|
#include "dialmgr.hxx"
|
|
#ifndef _UNO_LINGU_HXX
|
|
#include <unolingu.hxx>
|
|
#endif
|
|
#ifndef _USR_USTRING_HXX
|
|
//#include <usr/ustring.hxx>
|
|
#endif
|
|
|
|
using namespace ::rtl;
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::linguistic2;
|
|
|
|
#define S2U(s) StringToOUString(s, CHARSET_SYSTEM)
|
|
#define U2S(s) OUStringToString(s, CHARSET_SYSTEM)
|
|
|
|
// define ----------------------------------------------------------------
|
|
|
|
#define HYPHHERE '-'
|
|
#define CONTINUE_HYPH USHRT_MAX
|
|
|
|
// Dies ist nur ein Hack, weil an dieser Stelle das extern char aus hmwrap
|
|
// nicht bekannt ist, wird demnaechst in hmwrap durch ein define ersetzt.
|
|
#define SW_SOFT_HYPHEN '='
|
|
|
|
// class SvxHyphenEdit ---------------------------------------------------
|
|
|
|
SvxHyphenEdit::SvxHyphenEdit( Window* pParent, const ResId& rResId ) :
|
|
|
|
Edit( pParent, rResId )
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenEdit::KeyInput( const KeyEvent& rKEvt )
|
|
{
|
|
// sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
|
|
sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
|
|
|
|
switch ( nCode )
|
|
{
|
|
case KEY_LEFT:
|
|
( (SvxHyphenWordDialog*)GetParent() )->SelLeft();
|
|
break;
|
|
|
|
case KEY_RIGHT:
|
|
( (SvxHyphenWordDialog*)GetParent() )->SelRight();
|
|
break;
|
|
|
|
case KEY_TAB:
|
|
case KEY_ESCAPE:
|
|
case KEY_RETURN:
|
|
Edit::KeyInput(rKEvt);
|
|
break;
|
|
#ifdef MAC
|
|
case KEY_POINT:
|
|
// Command . abfangen
|
|
if ( nMod == KEY_MOD1 )
|
|
{
|
|
Edit::KeyInput( rKEvt );
|
|
break;
|
|
}
|
|
// kein break!
|
|
#endif
|
|
default:
|
|
Control::KeyInput( rKEvt ); // An den Dialog weiterleiten
|
|
break;
|
|
}
|
|
}
|
|
|
|
// class SvxHyphenWordDialog ---------------------------------------------
|
|
|
|
SvxHyphenWordDialog::SvxHyphenWordDialog( const String &rWord, LanguageType nLang,
|
|
Window* pParent,
|
|
Reference< XHyphenator > &xHyphen,
|
|
SvxSpellWrapper* pWrapper ) :
|
|
SfxModalDialog( pParent, SVX_RES( RID_SVXDLG_HYPHENATE ) ),
|
|
|
|
aWordFT ( this, ResId( FT_WORD ) ),
|
|
aWordEdit ( this, ResId( ED_WORD ) ),
|
|
aLeftBtn ( this, ResId( BTN_LEFT ) ),
|
|
aRightBtn ( this, ResId( BTN_RIGHT ) ),
|
|
aOkBtn ( this, ResId( BTN_HYPH_CUT ) ),
|
|
aCancelBtn ( this, ResId( BTN_HYPH_CANCEL ) ),
|
|
aContBtn ( this, ResId( BTN_HYPH_CONTINUE ) ),
|
|
aDelBtn ( this, ResId( BTN_HYPH_DELETE ) ),
|
|
aHelpBtn ( this, ResId( BTN_HYPH_HELP ) ),
|
|
aLabel ( GetText() ),
|
|
pHyphWrapper ( pWrapper ),
|
|
xHyphenator ( xHyphen ),
|
|
aActWord ( rWord ),
|
|
nActLanguage ( nLang ),
|
|
nHyphPos ( 0 ),
|
|
nOldPos ( 0 ),
|
|
bBusy ( sal_False )
|
|
{
|
|
aContBtn.SetClickHdl(
|
|
LINK( this, SvxHyphenWordDialog, ContinueHdl_Impl ) );
|
|
aOkBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, CutHdl_Impl ) );
|
|
aDelBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, DeleteHdl_Impl ) );
|
|
aCancelBtn.SetClickHdl(
|
|
LINK( this, SvxHyphenWordDialog, CancelHdl_Impl ) );
|
|
aLeftBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, Left_Impl ) );
|
|
aRightBtn.SetClickHdl( LINK( this, SvxHyphenWordDialog, Right_Impl ) );
|
|
|
|
aWordEdit.SetGetFocusHdl(
|
|
LINK( this, SvxHyphenWordDialog, GetFocusHdl_Impl ) );
|
|
|
|
Reference< XHyphenatedWord > xHyphWord( pWrapper ?
|
|
pWrapper->GetLast() : Reference< XInterface > () , UNO_QUERY );
|
|
DBG_ASSERT(xHyphWord.is(), "missing hyphenated word");
|
|
nMaxHyphenationPos = xHyphWord.is() ? xHyphWord->getHyphenationPos() : 0;
|
|
SetLabel_Impl( nLang );
|
|
|
|
InitControls_Impl();
|
|
aWordEdit.GrabFocus();
|
|
|
|
FreeResource();
|
|
|
|
// disable controls if service is not available
|
|
if (!xHyphenator.is())
|
|
Enable( sal_False );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenWordDialog::SelLeft()
|
|
{
|
|
String aTxt( aWordEdit.GetText() );
|
|
|
|
for ( xub_StrLen i = nOldPos + 1; i-- > 0 ; )
|
|
{
|
|
DBG_ASSERT(i <= aTxt.Len(), "index out of range");
|
|
if( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
|
|
{
|
|
aTxt.SetChar( i, sal_Unicode( HYPHHERE ) );
|
|
|
|
if ( nOldPos != 0 && nOldPos != aTxt.Len() )
|
|
aTxt.SetChar( nOldPos, sal_Unicode( SW_SOFT_HYPHEN ) );
|
|
nOldPos = i;
|
|
aWordEdit.SetText( aTxt );
|
|
aWordEdit.GrabFocus();
|
|
aWordEdit.SetSelection( Selection( i, i + 1 ) );
|
|
break;
|
|
}
|
|
}
|
|
nHyphPos = GetHyphIndex_Impl();
|
|
EnableLRBtn_Impl();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenWordDialog::SelRight()
|
|
{
|
|
String aTxt( aWordEdit.GetText() );
|
|
|
|
for ( xub_StrLen i = nOldPos + 1; i < aTxt.Len(); ++i )
|
|
{
|
|
if( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
|
|
{
|
|
aTxt.SetChar( i, sal_Unicode( HYPHHERE ) );
|
|
|
|
if ( nOldPos != 0 && nOldPos != aTxt.Len() )
|
|
aTxt.SetChar( nOldPos, sal_Unicode( SW_SOFT_HYPHEN ) );
|
|
nOldPos = i;
|
|
aWordEdit.SetText( aTxt );
|
|
aWordEdit.GrabFocus();
|
|
aWordEdit.SetSelection( Selection( i, i + 1 ) );
|
|
break;
|
|
}
|
|
}
|
|
nHyphPos = GetHyphIndex_Impl();
|
|
EnableLRBtn_Impl();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenWordDialog::EnableLRBtn_Impl()
|
|
{
|
|
String aTxt( aWordEdit.GetText() );
|
|
xub_StrLen nLen = aTxt.Len();
|
|
xub_StrLen i;
|
|
|
|
aRightBtn.Disable();
|
|
for ( i = nOldPos + 2; i < nLen; ++i )
|
|
{
|
|
if ( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
|
|
{
|
|
aRightBtn.Enable();
|
|
break;
|
|
}
|
|
}
|
|
|
|
DBG_ASSERT(nOldPos < aTxt.Len(), "nOldPos out of range");
|
|
if (nOldPos >= aTxt.Len())
|
|
nOldPos = aTxt.Len() - 1;
|
|
aLeftBtn.Disable();
|
|
for ( i = nOldPos; i-- > 0; )
|
|
{
|
|
if ( aTxt.GetChar( i ) == sal_Unicode( SW_SOFT_HYPHEN ) )
|
|
{
|
|
aLeftBtn.Enable();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
|
|
void SvxHyphenWordDialog::SetLabel_Impl( LanguageType nLang )
|
|
{
|
|
String aLangStr( ::GetLanguageString( nLang ) );
|
|
String aTmp( aLabel );
|
|
aTmp.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " (" ) );
|
|
aTmp.Append( aLangStr );
|
|
aTmp.Append( sal_Unicode( ')' ) );
|
|
SetText( aTmp );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
String SvxHyphenWordDialog::EraseUnusableHyphens_Impl(
|
|
Reference< XPossibleHyphens > &rxPossHyph,
|
|
sal_uInt16 _nMaxHyphenationPos )
|
|
{
|
|
// returns a String showing only those hyphen positions which will result
|
|
// in a line break if hyphenation is done there
|
|
|
|
String aTxt;
|
|
DBG_ASSERT(rxPossHyph.is(), "missing possible hyphens");
|
|
if (rxPossHyph.is())
|
|
{
|
|
aTxt = String( rxPossHyph->getPossibleHyphens() );
|
|
|
|
Sequence< sal_Int16 > aHyphenationPositions(
|
|
rxPossHyph->getHyphenationPositions() );
|
|
sal_Int32 nLen = aHyphenationPositions.getLength();
|
|
const sal_Int16 *pHyphenationPos = aHyphenationPositions.getConstArray();
|
|
|
|
// find position nIdx after which all hyphen positions are unusable
|
|
xub_StrLen nIdx = STRING_NOTFOUND,
|
|
nPos;
|
|
if (nLen)
|
|
{
|
|
xub_StrLen nStart = 0;
|
|
for (sal_Int32 i = 0; i < nLen; ++i)
|
|
{
|
|
if (pHyphenationPos[i] > _nMaxHyphenationPos)
|
|
break;
|
|
else
|
|
{
|
|
// find corresponding hyphen pos in string
|
|
nPos = aTxt.Search( sal_Unicode( SW_SOFT_HYPHEN ), nStart );
|
|
|
|
if (nStart == STRING_NOTFOUND)
|
|
break;
|
|
else
|
|
{
|
|
nIdx = nPos;
|
|
nStart = nPos + 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DBG_ASSERT(nIdx != STRING_NOTFOUND, "no usable hyphenation position")
|
|
|
|
// remove not usable hyphens from string
|
|
nPos = nIdx == STRING_NOTFOUND ? 0 : nIdx + 1;
|
|
String aTmp( sal_Unicode( SW_SOFT_HYPHEN ) ),
|
|
aEmpty;
|
|
while (nPos != STRING_NOTFOUND)
|
|
nPos = aTxt.SearchAndReplace( aTmp, aEmpty, nPos + 1 );
|
|
}
|
|
return aTxt;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenWordDialog::InitControls_Impl()
|
|
{
|
|
String aTxt;
|
|
xPossHyph = NULL;
|
|
if (xHyphenator.is())
|
|
{
|
|
lang::Locale aLocale( SvxCreateLocale(nActLanguage) );
|
|
xPossHyph = xHyphenator->createPossibleHyphens( aActWord, aLocale,
|
|
Sequence< PropertyValue >() );
|
|
if (xPossHyph.is())
|
|
{
|
|
aTxt = EraseUnusableHyphens_Impl( xPossHyph, nMaxHyphenationPos );
|
|
}
|
|
SetLabel_Impl( nActLanguage );
|
|
}
|
|
aWordEdit.SetText( aTxt );
|
|
|
|
nOldPos = aTxt.Len();
|
|
SelLeft();
|
|
EnableLRBtn_Impl();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void SvxHyphenWordDialog::ContinueHyph_Impl( sal_uInt16 nInsPos )
|
|
{
|
|
if ( nInsPos != CONTINUE_HYPH && xPossHyph.is())
|
|
{
|
|
if (nInsPos)
|
|
{
|
|
//String aTmp( U2S( xPossHyph->getPossibleHyphens() ) );
|
|
String aTmp( aWordEdit.GetText() );
|
|
DBG_ASSERT(nInsPos <= aTmp.Len() - 2, "wrong hyphen position");
|
|
|
|
sal_uInt16 nIdxPos = 0;
|
|
sal_uInt16 i = 0;
|
|
sal_Unicode c;
|
|
while (i < aTmp.Len() && HYPHHERE != (c = aTmp.GetChar(i++)) )
|
|
{
|
|
if (SW_SOFT_HYPHEN == c)
|
|
nIdxPos++;
|
|
}
|
|
|
|
Sequence< sal_Int16 > aSeq = xPossHyph->getHyphenationPositions();
|
|
sal_Int32 nLen = aSeq.getLength();
|
|
DBG_ASSERT(nLen, "empty sequence");
|
|
DBG_ASSERT(nIdxPos < nLen, "index out of range");
|
|
if (nLen && nIdxPos < nLen)
|
|
{
|
|
nInsPos = aSeq.getConstArray()[ nIdxPos ];
|
|
pHyphWrapper->InsertHyphen( nInsPos );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//! calling with 0 as argument will remove hyphens!
|
|
pHyphWrapper->InsertHyphen( nInsPos );
|
|
}
|
|
}
|
|
|
|
if ( pHyphWrapper->FindSpellError() )
|
|
{
|
|
Reference< XHyphenatedWord > xHyphWord( pHyphWrapper->GetLast(), UNO_QUERY );
|
|
|
|
// adapt actual word and language to new found hyphenation result
|
|
if(xHyphWord.is())
|
|
{
|
|
aActWord = String( xHyphWord->getWord() );
|
|
nActLanguage = SvxLocaleToLanguage( xHyphWord->getLocale() );
|
|
nMaxHyphenationPos = xHyphWord->getHyphenationPos();
|
|
InitControls_Impl();
|
|
}
|
|
}
|
|
else
|
|
EndDialog( RET_OK );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uInt16 SvxHyphenWordDialog::GetHyphIndex_Impl()
|
|
{
|
|
sal_uInt16 nPos = 0;
|
|
String aTxt(aWordEdit.GetText());
|
|
|
|
for ( sal_uInt16 i=0 ; i < aTxt.Len(); ++i )
|
|
{
|
|
sal_Unicode nChar = aTxt.GetChar( i );
|
|
|
|
if ( nChar == HYPHHERE )
|
|
break;
|
|
|
|
if ( nChar != SW_SOFT_HYPHEN )
|
|
nPos++;
|
|
}
|
|
return nPos;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, CutHdl_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
ContinueHyph_Impl( nHyphPos );
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, CutHdl_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, DeleteHdl_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
ContinueHyph_Impl();
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, DeleteHdl_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, ContinueHdl_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
ContinueHyph_Impl( CONTINUE_HYPH );
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, ContinueHdl_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, CancelHdl_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
pHyphWrapper->SpellEnd();
|
|
EndDialog( RET_CANCEL );
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, CancelHdl_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, Left_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
SelLeft();
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, Left_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, Right_Impl, Button *, EMPTYARG )
|
|
{
|
|
if( !bBusy )
|
|
{
|
|
bBusy = sal_True;
|
|
SelRight();
|
|
bBusy = sal_False;
|
|
}
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, Right_Impl, Button *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_INLINE_START( SvxHyphenWordDialog, GetFocusHdl_Impl, Edit *, EMPTYARG )
|
|
{
|
|
aWordEdit.SetSelection( Selection( nOldPos, nOldPos + 1 ) );
|
|
return 0;
|
|
}
|
|
IMPL_LINK_INLINE_END( SvxHyphenWordDialog, GetFocusHdl_Impl, Edit *, EMPTYARG )
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK( SvxHyphenWordDialog, LangError_Impl, void *, nLang )
|
|
{
|
|
// Status anzeigen
|
|
String aErr( ::GetLanguageString( (LanguageType)(sal_IntPtr)nLang ) );
|
|
aErr += SVX_RESSTR( RID_SVXSTR_HMERR_CHECKINSTALL );
|
|
InfoBox( this, aErr ).Execute();
|
|
return 0;
|
|
}
|
|
|
|
|