Files
libreoffice/svx/source/dialog/hyphen.cxx
Oliver Bolte 18ba2a7b08 INTEGRATION: CWS sb59 (1.6.62); FILE MERGED
2006/08/23 15:25:41 sb 1.6.62.1: #i67487# Made code warning-free (wntmsci10).
2006-10-12 11:15:24 +00:00

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;
}