summaryrefslogtreecommitdiff
path: root/editeng/source/misc
diff options
context:
space:
mode:
authorMathias Bauer <mba@openoffice.org>2010-01-06 19:26:54 +0100
committerMathias Bauer <mba@openoffice.org>2010-01-06 19:26:54 +0100
commit127e5f966ebebe604792f5707d543e8618c61c48 (patch)
tree6c08490489b6a0667308c28a52080619d6b82492 /editeng/source/misc
parentf18f649faac191ddee68deb8c4d472a6b760614e (diff)
#i107450#: move code from svx to new module editeng
Diffstat (limited to 'editeng/source/misc')
-rw-r--r--editeng/source/misc/SvXMLAutoCorrectExport.cxx120
-rw-r--r--editeng/source/misc/SvXMLAutoCorrectExport.hxx78
-rw-r--r--editeng/source/misc/SvXMLAutoCorrectImport.cxx269
-rw-r--r--editeng/source/misc/SvXMLAutoCorrectImport.hxx151
-rw-r--r--editeng/source/misc/acorrcfg.cxx681
-rw-r--r--editeng/source/misc/edtdlg.cxx39
-rw-r--r--editeng/source/misc/forbiddencharacterstable.cxx95
-rw-r--r--editeng/source/misc/hangulhanja.cxx1174
-rw-r--r--editeng/source/misc/lingu.src107
-rw-r--r--editeng/source/misc/makefile.mk71
-rw-r--r--editeng/source/misc/splwrap.cxx637
-rw-r--r--editeng/source/misc/svxacorr.cxx2706
-rw-r--r--editeng/source/misc/swafopt.cxx163
-rw-r--r--editeng/source/misc/txtrange.cxx722
-rw-r--r--editeng/source/misc/unolingu.cxx1377
15 files changed, 8390 insertions, 0 deletions
diff --git a/editeng/source/misc/SvXMLAutoCorrectExport.cxx b/editeng/source/misc/SvXMLAutoCorrectExport.cxx
new file mode 100644
index 0000000000..05d11181b9
--- /dev/null
+++ b/editeng/source/misc/SvXMLAutoCorrectExport.cxx
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SvXMLAutoCorrectExport.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+#include <SvXMLAutoCorrectExport.hxx>
+#define _SVSTDARR_STRINGSISORTDTOR
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using namespace ::rtl;
+
+// #110680#
+SvXMLAutoCorrectExport::SvXMLAutoCorrectExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ const SvxAutocorrWordList * pNewAutocorr_List,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler)
+: SvXMLExport( xServiceFactory, rFileName, rHandler ),
+ pAutocorr_List( pNewAutocorr_List )
+{
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_BLOCK_LIST),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+sal_uInt32 SvXMLAutoCorrectExport::exportDoc(enum XMLTokenEnum /*eClass*/)
+{
+ GetDocHandler()->startDocument();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ {
+ SvXMLElementExport aRoot (*this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK_LIST, sal_True, sal_True);
+ sal_uInt16 nBlocks= pAutocorr_List->Count();
+ for ( sal_uInt16 i = 0; i < nBlocks; i++)
+ {
+ SvxAutocorrWord* p = pAutocorr_List->GetObject(i);
+
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_ABBREVIATED_NAME,
+ OUString(p->GetShort()));
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_NAME,
+ OUString(p->IsTextOnly() ? p->GetLong() : p->GetShort()));
+
+ SvXMLElementExport aBlock( *this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK, sal_True, sal_True);
+ }
+ }
+ GetDocHandler()->endDocument();
+ return 0;
+}
+
+// #110680#
+SvXMLExceptionListExport::SvXMLExceptionListExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ const SvStringsISortDtor &rNewList,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler)
+: SvXMLExport( xServiceFactory, rFileName, rHandler ),
+ rList( rNewList )
+{
+ _GetNamespaceMap().Add( GetXMLToken ( XML_NP_BLOCK_LIST ),
+ GetXMLToken ( XML_N_BLOCK_LIST ),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+sal_uInt32 SvXMLExceptionListExport::exportDoc(enum XMLTokenEnum /*eClass*/)
+{
+ GetDocHandler()->startDocument();
+
+ AddAttribute ( XML_NAMESPACE_NONE,
+ _GetNamespaceMap().GetAttrNameByKey ( XML_NAMESPACE_BLOCKLIST ),
+ _GetNamespaceMap().GetNameByKey ( XML_NAMESPACE_BLOCKLIST ) );
+ {
+ SvXMLElementExport aRoot (*this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK_LIST, sal_True, sal_True);
+ sal_uInt16 nBlocks= rList.Count();
+ for ( sal_uInt16 i = 0; i < nBlocks; i++)
+ {
+ AddAttribute( XML_NAMESPACE_BLOCKLIST,
+ XML_ABBREVIATED_NAME,
+ OUString( *rList[i] ) );
+ SvXMLElementExport aBlock( *this, XML_NAMESPACE_BLOCKLIST, XML_BLOCK, sal_True, sal_True);
+ }
+ }
+ GetDocHandler()->endDocument();
+ return 0;
+}
diff --git a/editeng/source/misc/SvXMLAutoCorrectExport.hxx b/editeng/source/misc/SvXMLAutoCorrectExport.hxx
new file mode 100644
index 0000000000..b88fbc7287
--- /dev/null
+++ b/editeng/source/misc/SvXMLAutoCorrectExport.hxx
@@ -0,0 +1,78 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SvXMLAutoCorrectExport.hxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SV_XMLAUTOCORRECTEXPORT_HXX
+#define _SV_XMLAUTOCORRECTEXPORT_HXX
+
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <editeng/svxacorr.hxx>
+
+class SvXMLAutoCorrectExport : public SvXMLExport
+{
+private:
+ const SvxAutocorrWordList *pAutocorr_List;
+public:
+ // #110680#
+ SvXMLAutoCorrectExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ const SvxAutocorrWordList * pNewAutocorr_List,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler);
+
+ virtual ~SvXMLAutoCorrectExport ( void ) {}
+ sal_uInt32 exportDoc(enum ::xmloff::token::XMLTokenEnum eClass);
+ void _ExportAutoStyles() {}
+ void _ExportMasterStyles () {}
+ void _ExportContent() {}
+};
+
+class SvStringsISortDtor;
+
+class SvXMLExceptionListExport : public SvXMLExport
+{
+private:
+ const SvStringsISortDtor & rList;
+public:
+ // #110680#
+ SvXMLExceptionListExport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ const SvStringsISortDtor &rNewList,
+ const rtl::OUString &rFileName,
+ com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler> &rHandler);
+
+ virtual ~SvXMLExceptionListExport ( void ) {}
+ sal_uInt32 exportDoc(enum ::xmloff::token::XMLTokenEnum eClass);
+ void _ExportAutoStyles() {}
+ void _ExportMasterStyles () {}
+ void _ExportContent() {}
+};
+#endif
diff --git a/editeng/source/misc/SvXMLAutoCorrectImport.cxx b/editeng/source/misc/SvXMLAutoCorrectImport.cxx
new file mode 100644
index 0000000000..0230e849b8
--- /dev/null
+++ b/editeng/source/misc/SvXMLAutoCorrectImport.cxx
@@ -0,0 +1,269 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SvXMLAutoCorrectImport.cxx,v $
+ * $Revision: 1.14 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+#include <SvXMLAutoCorrectImport.hxx>
+#ifndef _APP_HXX //autogen
+#include <vcl/svapp.hxx>
+#endif
+
+#define _SVSTDARR_STRINGSISORTDTOR
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <xmloff/xmltoken.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using namespace ::rtl;
+
+
+static OUString sBlockList ( RTL_CONSTASCII_USTRINGPARAM ( "_block-list" ) );
+
+// #110680#
+SvXMLAutoCorrectImport::SvXMLAutoCorrectImport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SvxAutocorrWordList *pNewAutocorr_List,
+ SvxAutoCorrect &rNewAutoCorrect,
+ const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rNewStorage)
+: SvXMLImport( xServiceFactory ),
+ pAutocorr_List (pNewAutocorr_List),
+ rAutoCorrect ( rNewAutoCorrect ),
+ xStorage ( rNewStorage )
+{
+ GetNamespaceMap().Add(
+ sBlockList,
+ GetXMLToken ( XML_N_BLOCK_LIST),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+SvXMLAutoCorrectImport::~SvXMLAutoCorrectImport ( void ) throw ()
+{
+}
+
+SvXMLImportContext *SvXMLAutoCorrectImport::CreateContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+
+ if( XML_NAMESPACE_BLOCKLIST == nPrefix &&
+ IsXMLToken ( rLocalName, XML_BLOCK_LIST ) )
+ pContext = new SvXMLWordListContext( *this, nPrefix, rLocalName, xAttrList );
+ else
+ pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
+ return pContext;
+}
+
+SvXMLWordListContext::SvXMLWordListContext(
+ SvXMLAutoCorrectImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const com::sun::star::uno::Reference<
+ com::sun::star::xml::sax::XAttributeList > & /*xAttrList*/ ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SvXMLWordListContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+
+ if (nPrefix == XML_NAMESPACE_BLOCKLIST &&
+ IsXMLToken ( rLocalName, XML_BLOCK ) )
+ pContext = new SvXMLWordContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+SvXMLWordListContext::~SvXMLWordListContext ( void )
+{
+}
+
+SvXMLWordContext::SvXMLWordContext(
+ SvXMLAutoCorrectImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const com::sun::star::uno::Reference<
+ com::sun::star::xml::sax::XAttributeList > & xAttrList ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+ String sRight, sWrong;
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+
+ for (sal_Int16 i=0; i < nAttrCount; i++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName);
+ const OUString& rAttrValue = xAttrList->getValueByIndex( i );
+ if (XML_NAMESPACE_BLOCKLIST == nAttrPrefix)
+ {
+ if ( IsXMLToken ( aLocalName, XML_ABBREVIATED_NAME ) )
+ {
+ sWrong = rAttrValue;
+ }
+ else if ( IsXMLToken ( aLocalName, XML_NAME ) )
+ {
+ sRight = rAttrValue;
+ }
+ }
+ }
+ if (!sWrong.Len() || !sRight.Len() )
+ return;
+
+// const International& rInter = Application::GetAppInternational();
+// BOOL bOnlyTxt = COMPARE_EQUAL != rInter.Compare( sRight, sWrong, INTN_COMPARE_IGNORECASE );
+ BOOL bOnlyTxt = sRight != sWrong;
+ if( !bOnlyTxt )
+ {
+ String sLongSave( sRight );
+ if( !rLocalRef.rAutoCorrect.GetLongText( rLocalRef.xStorage, String(), sWrong, sRight ) &&
+ sLongSave.Len() )
+ {
+ sRight = sLongSave;
+ bOnlyTxt = TRUE;
+ }
+ }
+ SvxAutocorrWordPtr pNew = new SvxAutocorrWord( sWrong, sRight, bOnlyTxt );
+
+ if( !rLocalRef.pAutocorr_List->Insert( pNew ) )
+ delete pNew;
+}
+
+SvXMLWordContext::~SvXMLWordContext ( void )
+{
+}
+
+// #110680#
+SvXMLExceptionListImport::SvXMLExceptionListImport(
+ const uno::Reference< lang::XMultiServiceFactory > xServiceFactory,
+ SvStringsISortDtor & rNewList )
+: SvXMLImport( xServiceFactory ),
+ rList (rNewList)
+{
+ GetNamespaceMap().Add(
+ sBlockList,
+ GetXMLToken ( XML_N_BLOCK_LIST),
+ XML_NAMESPACE_BLOCKLIST );
+}
+
+SvXMLExceptionListImport::~SvXMLExceptionListImport ( void ) throw ()
+{
+}
+
+SvXMLImportContext *SvXMLExceptionListImport::CreateContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+
+ if( XML_NAMESPACE_BLOCKLIST==nPrefix &&
+ IsXMLToken ( rLocalName, XML_BLOCK_LIST ) )
+ pContext = new SvXMLExceptionListContext( *this, nPrefix, rLocalName, xAttrList );
+ else
+ pContext = SvXMLImport::CreateContext( nPrefix, rLocalName, xAttrList );
+ return pContext;
+}
+
+SvXMLExceptionListContext::SvXMLExceptionListContext(
+ SvXMLExceptionListImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const com::sun::star::uno::Reference<
+ com::sun::star::xml::sax::XAttributeList > & /* xAttrList */ ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+}
+
+SvXMLImportContext *SvXMLExceptionListContext::CreateChildContext(
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList > & xAttrList )
+{
+ SvXMLImportContext *pContext = 0;
+
+ if (nPrefix == XML_NAMESPACE_BLOCKLIST &&
+ IsXMLToken ( rLocalName, XML_BLOCK ) )
+ pContext = new SvXMLExceptionContext (rLocalRef, nPrefix, rLocalName, xAttrList);
+ else
+ pContext = new SvXMLImportContext( rLocalRef, nPrefix, rLocalName);
+ return pContext;
+}
+SvXMLExceptionListContext::~SvXMLExceptionListContext ( void )
+{
+}
+
+SvXMLExceptionContext::SvXMLExceptionContext(
+ SvXMLExceptionListImport& rImport,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const com::sun::star::uno::Reference<
+ com::sun::star::xml::sax::XAttributeList > & xAttrList ) :
+ SvXMLImportContext ( rImport, nPrefix, rLocalName ),
+ rLocalRef(rImport)
+{
+ String sWord;
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+
+ for (sal_Int16 i=0; i < nAttrCount; i++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex( i );
+ OUString aLocalName;
+ sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName( rAttrName, &aLocalName);
+ const OUString& rAttrValue = xAttrList->getValueByIndex( i );
+ if (XML_NAMESPACE_BLOCKLIST == nAttrPrefix)
+ {
+ if ( IsXMLToken ( aLocalName, XML_ABBREVIATED_NAME ) )
+ {
+ sWord = rAttrValue;
+ }
+ }
+ }
+ if (!sWord.Len() )
+ return;
+
+ String * pNew = new String( sWord );
+
+ if( !rLocalRef.rList.Insert( pNew ) )
+ delete pNew;
+}
+
+SvXMLExceptionContext::~SvXMLExceptionContext ( void )
+{
+}
diff --git a/editeng/source/misc/SvXMLAutoCorrectImport.hxx b/editeng/source/misc/SvXMLAutoCorrectImport.hxx
new file mode 100644
index 0000000000..8118782961
--- /dev/null
+++ b/editeng/source/misc/SvXMLAutoCorrectImport.hxx
@@ -0,0 +1,151 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: SvXMLAutoCorrectImport.hxx,v $
+ * $Revision: 1.11 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _SV_XMLAUTOCORRECTIMPORT_HXX
+#define _SV_XMLAUTOCORRECTIMPORT_HXX
+
+#ifndef _SVSTOR_HXX
+#include <sot/storage.hxx>
+#endif
+#include <xmloff/xmlictxt.hxx>
+#include <xmloff/xmlimp.hxx>
+#include <xmloff/nmspmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <editeng/svxacorr.hxx>
+
+class SvXMLAutoCorrectImport : public SvXMLImport
+{
+protected:
+
+ // This method is called after the namespace map has been updated, but
+ // before a context for the current element has been pushed.
+ virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+public:
+ SvxAutocorrWordList *pAutocorr_List;
+ SvxAutoCorrect &rAutoCorrect;
+ com::sun::star::uno::Reference < com::sun::star::embed::XStorage > xStorage;
+ //SvStorageRef &rStorage;
+
+ // #110680#
+ SvXMLAutoCorrectImport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SvxAutocorrWordList *pNewAutocorr_List,
+ SvxAutoCorrect &rNewAutoCorrect,
+ const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rNewStorage);
+
+ ~SvXMLAutoCorrectImport ( void ) throw ();
+};
+
+class SvXMLWordListContext : public SvXMLImportContext
+{
+private:
+ SvXMLAutoCorrectImport & rLocalRef;
+public:
+ SvXMLWordListContext ( SvXMLAutoCorrectImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SvXMLWordListContext ( void );
+};
+
+class SvXMLWordContext : public SvXMLImportContext
+{
+private:
+ SvXMLAutoCorrectImport & rLocalRef;
+public:
+ SvXMLWordContext ( SvXMLAutoCorrectImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SvXMLWordContext ( void );
+};
+
+
+class SvXMLExceptionListImport : public SvXMLImport
+{
+protected:
+
+ // This method is called after the namespace map has been updated, but
+ // before a context for the current element has been pushed.
+ virtual SvXMLImportContext *CreateContext( sal_uInt16 nPrefix,
+ const ::rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+public:
+ SvStringsISortDtor &rList;
+
+ // #110680#
+ SvXMLExceptionListImport(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xServiceFactory,
+ SvStringsISortDtor & rNewList );
+
+ ~SvXMLExceptionListImport ( void ) throw ();
+};
+
+class SvXMLExceptionListContext : public SvXMLImportContext
+{
+private:
+ SvXMLExceptionListImport & rLocalRef;
+public:
+ SvXMLExceptionListContext ( SvXMLExceptionListImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ virtual SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SvXMLExceptionListContext ( void );
+};
+
+class SvXMLExceptionContext : public SvXMLImportContext
+{
+private:
+ SvXMLExceptionListImport & rLocalRef;
+public:
+ SvXMLExceptionContext ( SvXMLExceptionListImport& rImport,
+ sal_uInt16 nPrefix,
+ const rtl::OUString& rLocalName,
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
+ ~SvXMLExceptionContext ( void );
+};
+
+
+#endif
diff --git a/editeng/source/misc/acorrcfg.cxx b/editeng/source/misc/acorrcfg.cxx
new file mode 100644
index 0000000000..9c90f9e9e9
--- /dev/null
+++ b/editeng/source/misc/acorrcfg.cxx
@@ -0,0 +1,681 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: acorrcfg.cxx,v $
+ * $Revision: 1.11 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <editeng/acorrcfg.hxx>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <svl/urihelper.hxx>
+
+#include <editeng/svxacorr.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using namespace utl;
+using namespace rtl;
+using namespace com::sun::star::uno;
+
+#define C2U(cChar) OUString::createFromAscii(cChar)
+
+static SvxAutoCorrCfg* pAutoCorrCfg = 0;
+
+/*--------------------------------------------------------------------
+ Beschreibung: Ctor Dtor
+ --------------------------------------------------------------------*/
+
+SvxAutoCorrCfg::SvxAutoCorrCfg() :
+ aBaseConfig(*this),
+ aSwConfig(*this),
+ bFileRel(TRUE),
+ bNetRel(TRUE),
+ bAutoTextTip(TRUE),
+ bAutoTextPreview(FALSE),
+ bAutoFmtByInput(TRUE),
+ bSearchInAllCategories(FALSE)
+{
+ SvtPathOptions aPathOpt;
+ String sSharePath, sUserPath, sAutoPath( aPathOpt.GetAutoCorrectPath() );
+
+ String* pS = &sSharePath;
+ for( USHORT n = 0; n < 2; ++n, pS = &sUserPath )
+ {
+ *pS = sAutoPath.GetToken( n, ';' );
+ INetURLObject aPath( *pS );
+ aPath.insertName( String::CreateFromAscii("acor") );
+ *pS = aPath.GetMainURL(INetURLObject::DECODE_TO_IURI);
+ }
+ pAutoCorrect = new SvxAutoCorrect( sSharePath, sUserPath );
+
+ aBaseConfig.Load(sal_True);
+ aSwConfig.Load(sal_True);
+}
+
+SvxAutoCorrCfg::~SvxAutoCorrCfg()
+{
+ delete pAutoCorrect;
+}
+
+void SvxAutoCorrCfg::SetAutoCorrect( SvxAutoCorrect* pNew )
+{
+ if( pNew && pNew != pAutoCorrect )
+ {
+ if( pAutoCorrect->GetFlags() != pNew->GetFlags() )
+ {
+ aBaseConfig.SetModified();
+ aSwConfig.SetModified();
+ }
+ delete pAutoCorrect;
+ pAutoCorrect = pNew;
+ }
+}
+/*-- 12.10.00 11:44:17---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+Sequence<OUString> SvxBaseAutoCorrCfg::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Exceptions/TwoCapitalsAtStart", // 0
+ "Exceptions/CapitalAtStartSentence", // 1
+ "UseReplacementTable", // 2
+ "TwoCapitalsAtStart", // 3
+ "CapitalAtStartSentence", // 4
+ "ChangeUnderlineWeight", // 5
+ "SetInetAttribute", // 6
+ "ChangeOrdinalNumber", // 7
+ "ChangeFraction", // 8
+ "ChangeDash", // 9
+ "RemoveDoubleSpaces", // 10
+ "ReplaceSingleQuote", // 11
+ "SingleQuoteAtStart", // 12
+ "SingleQuoteAtEnd", // 13
+ "ReplaceDoubleQuote", // 14
+ "DoubleQuoteAtStart", // 15
+ "DoubleQuoteAtEnd" // 16
+ };
+ const int nCount = 17;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ return aNames;
+}
+/*-- 12.10.00 11:44:18---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxBaseAutoCorrCfg::Load(sal_Bool bInit)
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ if(bInit)
+ EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() == aNames.getLength())
+ {
+ long nFlags = 0; // default alles aus
+ sal_Int32 nTemp = 0;
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= SaveWordCplSttLst;
+ break;//"Exceptions/TwoCapitalsAtStart",
+ case 1:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= SaveWordWrdSttLst;
+ break;//"Exceptions/CapitalAtStartSentence",
+ case 2:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= Autocorrect;
+ break;//"UseReplacementTable",
+ case 3:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= CptlSttWrd;
+ break;//"TwoCapitalsAtStart",
+ case 4:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= CptlSttSntnc;
+ break;//"CapitalAtStartSentence",
+ case 5:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgWeightUnderl;
+ break;//"ChangeUnderlineWeight",
+ case 6:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= SetINetAttr;
+ break;//"SetInetAttribute",
+ case 7:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgOrdinalNumber;
+ break;//"ChangeOrdinalNumber",
+ case 8:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgFractionSymbol;
+ break;//"ChangeFraction",
+ case 9:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgToEnEmDash;
+ break;//"ChangeDash",
+ case 10:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= IngnoreDoubleSpace;
+ break;//"RemoveDoubleSpaces",
+ case 11:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgSglQuotes;
+ break;//"ReplaceSingleQuote",
+ case 12:
+ pValues[nProp] >>= nTemp;
+ rParent.pAutoCorrect->SetStartSingleQuote(
+ sal::static_int_cast< sal_Unicode >( nTemp ) );
+ break;//"SingleQuoteAtStart",
+ case 13:
+ pValues[nProp] >>= nTemp;
+ rParent.pAutoCorrect->SetEndSingleQuote(
+ sal::static_int_cast< sal_Unicode >( nTemp ) );
+ break;//"SingleQuoteAtEnd",
+ case 14:
+ if(*(sal_Bool*)pValues[nProp].getValue())
+ nFlags |= ChgQuotes;
+ break;//"ReplaceDoubleQuote",
+ case 15:
+ pValues[nProp] >>= nTemp;
+ rParent.pAutoCorrect->SetStartDoubleQuote(
+ sal::static_int_cast< sal_Unicode >( nTemp ) );
+ break;//"DoubleQuoteAtStart",
+ case 16:
+ pValues[nProp] >>= nTemp;
+ rParent.pAutoCorrect->SetEndDoubleQuote(
+ sal::static_int_cast< sal_Unicode >( nTemp ) );
+ break;//"DoubleQuoteAtEnd"
+ }
+ }
+ }
+ if( nFlags )
+ rParent.pAutoCorrect->SetAutoCorrFlag( nFlags, TRUE );
+ rParent.pAutoCorrect->SetAutoCorrFlag( ( 0xffff & ~nFlags ), FALSE );
+
+ }
+}
+/*-- 12.10.00 11:44:19---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+SvxBaseAutoCorrCfg::SvxBaseAutoCorrCfg(SvxAutoCorrCfg& rPar) :
+ utl::ConfigItem(C2U("Office.Common/AutoCorrect")),
+ rParent(rPar)
+{
+}
+/*-- 12.10.00 11:44:19---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+SvxBaseAutoCorrCfg::~SvxBaseAutoCorrCfg()
+{
+}
+/*-- 12.10.00 11:44:20---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxBaseAutoCorrCfg::Commit()
+{
+ Sequence<OUString> aNames( GetPropertyNames() );
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ BOOL bVal;
+ const long nFlags = rParent.pAutoCorrect->GetFlags();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0:
+ bVal = 0 != (nFlags & SaveWordCplSttLst);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"Exceptions/TwoCapitalsAtStart",
+ case 1:
+ bVal = 0 != (nFlags & SaveWordWrdSttLst);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"Exceptions/CapitalAtStartSentence",
+ case 2:
+ bVal = 0 != (nFlags & Autocorrect);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"UseReplacementTable",
+ case 3:
+ bVal = 0 != (nFlags & CptlSttWrd);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"TwoCapitalsAtStart",
+ case 4:
+ bVal = 0 != (nFlags & CptlSttSntnc);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"CapitalAtStartSentence",
+ case 5:
+ bVal = 0 != (nFlags & ChgWeightUnderl);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ChangeUnderlineWeight",
+ case 6:
+ bVal = 0 != (nFlags & SetINetAttr);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"SetInetAttribute",
+ case 7:
+ bVal = 0 != (nFlags & ChgOrdinalNumber);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ChangeOrdinalNumber",
+ case 8:
+ bVal = 0 != (nFlags & ChgFractionSymbol);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ChangeFraction",
+ case 9:
+ bVal = 0 != (nFlags & ChgToEnEmDash);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ChangeDash",
+ case 10:
+ bVal = 0 != (nFlags & IngnoreDoubleSpace);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"RemoveDoubleSpaces",
+ case 11:
+ bVal = 0 != (nFlags & ChgSglQuotes);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ReplaceSingleQuote",
+ case 12:
+ pValues[nProp] <<= (sal_Int32)rParent.pAutoCorrect->GetStartSingleQuote();
+ break;//"SingleQuoteAtStart",
+ case 13:
+ pValues[nProp] <<= (sal_Int32) rParent.pAutoCorrect->GetEndSingleQuote();
+ break;//"SingleQuoteAtEnd",
+ case 14:
+ bVal = 0 != (nFlags & ChgQuotes);
+ pValues[nProp].setValue(&bVal, rType);
+ break;//"ReplaceDoubleQuote",
+ case 15:
+ pValues[nProp] <<= (sal_Int32) rParent.pAutoCorrect->GetStartDoubleQuote();
+ break;//"DoubleQuoteAtStart",
+ case 16:
+ pValues[nProp] <<= (sal_Int32) rParent.pAutoCorrect->GetEndDoubleQuote();
+ break;//"DoubleQuoteAtEnd"
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+/*-- 12.10.00 11:44:21---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxBaseAutoCorrCfg::Notify( const Sequence<OUString>& /* aPropertyNames */)
+{
+ Load(sal_False);
+}
+/*-- 12.10.00 11:51:48---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+Sequence<OUString> SvxSwAutoCorrCfg::GetPropertyNames()
+{
+ static const char* aPropNames[] =
+ {
+ "Text/FileLinks", // 0
+ "Text/InternetLinks", // 1
+ "Text/ShowPreview", // 2
+ "Text/ShowToolTip", // 3
+ "Text/SearchInAllCategories", // 4
+ "Format/Option/UseReplacementTable", // 5
+ "Format/Option/TwoCapitalsAtStart", // 6
+ "Format/Option/CapitalAtStartSentence", // 7
+ "Format/Option/ChangeUnderlineWeight", // 8
+ "Format/Option/SetInetAttribute", // 9
+ "Format/Option/ChangeOrdinalNumber", //10
+ "Format/Option/ChangeFraction", //11
+ "Format/Option/ChangeDash", //12
+ "Format/Option/DelEmptyParagraphs", //13
+ "Format/Option/ReplaceUserStyle", //14
+ "Format/Option/ChangeToBullets/Enable", //15
+ "Format/Option/ChangeToBullets/SpecialCharacter/Char", //16
+ "Format/Option/ChangeToBullets/SpecialCharacter/Font", //17
+ "Format/Option/ChangeToBullets/SpecialCharacter/FontFamily", //18
+ "Format/Option/ChangeToBullets/SpecialCharacter/FontCharset", //19
+ "Format/Option/ChangeToBullets/SpecialCharacter/FontPitch", //20
+ "Format/Option/ReplaceQuote", //21
+ "Format/Option/CombineParagraphs", //22
+ "Format/Option/CombineValue", //23
+ "Format/Option/DelSpacesAtStartEnd", //24
+ "Format/Option/DelSpacesBetween", //25
+ "Format/ByInput/Enable", //26
+ "Format/ByInput/ChangeDash", //27
+ "Format/ByInput/ApplyNumbering/Enable", //28
+ "Format/ByInput/ChangeToBorders", //29
+ "Format/ByInput/ChangeToTable", //30
+ "Format/ByInput/ReplaceStyle", //31
+ "Format/ByInput/DelSpacesAtStartEnd", //32
+ "Format/ByInput/DelSpacesBetween", //33
+ "Completion/Enable", //34
+ "Completion/MinWordLen", //35
+ "Completion/MaxListLen", //36
+ "Completion/CollectWords", //37
+ "Completion/EndlessList", //38
+ "Completion/AppendBlank", //39
+ "Completion/ShowAsTip", //40
+ "Completion/AcceptKey", //41
+ "Completion/KeepList", //42
+ "Format/ByInput/ApplyNumbering/SpecialCharacter/Char", //43
+ "Format/ByInput/ApplyNumbering/SpecialCharacter/Font", //44
+ "Format/ByInput/ApplyNumbering/SpecialCharacter/FontFamily", //45
+ "Format/ByInput/ApplyNumbering/SpecialCharacter/FontCharset", //46
+ "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch", //47
+ };
+ const int nCount = 48;
+ Sequence<OUString> aNames(nCount);
+ OUString* pNames = aNames.getArray();
+ for(int i = 0; i < nCount; i++)
+ pNames[i] = OUString::createFromAscii(aPropNames[i]);
+ return aNames;
+}
+/*-- 12.10.00 11:51:48---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxSwAutoCorrCfg::Load(sal_Bool bInit)
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+ Sequence<Any> aValues = GetProperties(aNames);
+ if(bInit)
+ EnableNotification(aNames);
+ const Any* pValues = aValues.getConstArray();
+ DBG_ASSERT(aValues.getLength() == aNames.getLength(), "GetProperties failed");
+ if(aValues.getLength() == aNames.getLength())
+ {
+ SvxSwAutoFmtFlags& rSwFlags = rParent.pAutoCorrect->GetSwFlags();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ if(pValues[nProp].hasValue())
+ {
+ switch(nProp)
+ {
+ case 0: rParent.bFileRel = *(sal_Bool*)pValues[nProp].getValue(); break; // "Text/FileLinks",
+ case 1: rParent.bNetRel = *(sal_Bool*)pValues[nProp].getValue(); break; // "Text/InternetLinks",
+ case 2: rParent.bAutoTextPreview = *(sal_Bool*)pValues[nProp].getValue(); break; // "Text/ShowPreview",
+ case 3: rParent.bAutoTextTip = *(sal_Bool*)pValues[nProp].getValue(); break; // "Text/ShowToolTip",
+ case 4: rParent.bSearchInAllCategories = *(sal_Bool*)pValues[nProp].getValue(); break; //"Text/SearchInAllCategories"
+ case 5: rSwFlags.bAutoCorrect = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/UseReplacementTable",
+ case 6: rSwFlags.bCptlSttSntnc = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/TwoCapitalsAtStart",
+ case 7: rSwFlags.bCptlSttWrd = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/CapitalAtStartSentence",
+ case 8: rSwFlags.bChgWeightUnderl = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ChangeUnderlineWeight",
+ case 9: rSwFlags.bSetINetAttr = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/SetInetAttribute",
+ case 10: rSwFlags.bChgOrdinalNumber = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ChangeOrdinalNumber",
+ case 11: rSwFlags.bChgFracionSymbol = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ChangeFraction",
+// it doesn't exist here - the common flags are used for that -> LM
+// case 12: rSwFlags.bChgToEnEmDash = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ChangeDash",
+ case 13: rSwFlags.bDelEmptyNode = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/DelEmptyParagraphs",
+ case 14: rSwFlags.bChgUserColl = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ReplaceUserStyle",
+ case 15: rSwFlags.bChgEnumNum = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ChangeToBullets/Enable",
+ case 16:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.cBullet =
+ sal::static_int_cast< sal_Unicode >(nVal);
+ }
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/Char",
+ case 17:
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rSwFlags.aBulletFont.SetName(sTemp);
+ }
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/Font",
+ case 18:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aBulletFont.SetFamily(FontFamily(nVal));
+ }
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontFamily",
+ case 19:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aBulletFont.SetCharSet(CharSet(nVal));
+ }
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontCharset",
+ case 20:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aBulletFont.SetPitch(FontPitch(nVal));
+ }
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontPitch",
+ case 21: rSwFlags.bReplaceQuote = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/ReplaceQuote",
+ case 22: rSwFlags.bRightMargin = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/CombineParagraphs",
+ case 23:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.nRightMargin =
+ sal::static_int_cast< BYTE >(nVal);
+ }
+ break; // "Format/Option/CombineValue",
+ case 24: rSwFlags.bAFmtDelSpacesAtSttEnd = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/DelSpacesAtStartEnd",
+ case 25: rSwFlags.bAFmtDelSpacesBetweenLines = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/Option/DelSpacesBetween",
+ case 26: rParent.bAutoFmtByInput = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/Enable",
+ case 27: rSwFlags.bChgToEnEmDash = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/ChangeDash",
+ case 28: rSwFlags.bSetNumRule = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/ApplyNumbering/Enable",
+ case 29: rSwFlags.bSetBorder = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/ChangeToBorders",
+ case 30: rSwFlags.bCreateTable = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/ChangeToTable",
+ case 31: rSwFlags.bReplaceStyles = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/ReplaceStyle",
+ case 32: rSwFlags.bAFmtByInpDelSpacesAtSttEnd = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/DelSpacesAtStartEnd",
+ case 33: rSwFlags.bAFmtByInpDelSpacesBetweenLines = *(sal_Bool*)pValues[nProp].getValue(); break; // "Format/ByInput/DelSpacesBetween",
+ case 34: rSwFlags.bAutoCompleteWords = *(sal_Bool*)pValues[nProp].getValue(); break; // "Completion/Enable",
+ case 35:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.nAutoCmpltWordLen =
+ sal::static_int_cast< USHORT >(nVal);
+ }
+ break; // "Completion/MinWordLen",
+ case 36:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.nAutoCmpltListLen =
+ sal::static_int_cast< USHORT >(nVal);
+ }
+ break; // "Completion/MaxListLen",
+ case 37: rSwFlags.bAutoCmpltCollectWords = *(sal_Bool*)pValues[nProp].getValue(); break; // "Completion/CollectWords",
+ case 38: rSwFlags.bAutoCmpltEndless = *(sal_Bool*)pValues[nProp].getValue(); break; // "Completion/EndlessList",
+ case 39: rSwFlags.bAutoCmpltAppendBlanc = *(sal_Bool*)pValues[nProp].getValue(); break; // "Completion/AppendBlank",
+ case 40: rSwFlags.bAutoCmpltShowAsTip = *(sal_Bool*)pValues[nProp].getValue(); break; // "Completion/ShowAsTip",
+ case 41:
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.nAutoCmpltExpandKey =
+ sal::static_int_cast< USHORT >(nVal);
+ }
+ break; // "Completion/AcceptKey"
+ case 42 :rSwFlags.bAutoCmpltKeepList = *(sal_Bool*)pValues[nProp].getValue(); break;//"Completion/KeepList"
+ case 43 :
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.cByInputBullet =
+ sal::static_int_cast< sal_Unicode >(nVal);
+ }
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/Char",
+ case 44 :
+ {
+ OUString sTemp; pValues[nProp] >>= sTemp;
+ rSwFlags.aByInputBulletFont.SetName(sTemp);
+ }
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/Font",
+ case 45 :
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aByInputBulletFont.SetFamily(FontFamily(nVal));
+ }
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontFamily",
+ case 46 :
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aByInputBulletFont.SetCharSet(CharSet(nVal));
+ }
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontCharset",
+ case 47 :
+ {
+ sal_Int32 nVal = 0; pValues[nProp] >>= nVal;
+ rSwFlags.aByInputBulletFont.SetPitch(FontPitch(nVal));
+ }
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch",
+ }
+ }
+ }
+ }
+}
+/*-- 12.10.00 11:51:48---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+SvxSwAutoCorrCfg::SvxSwAutoCorrCfg(SvxAutoCorrCfg& rPar) :
+ utl::ConfigItem(C2U("Office.Writer/AutoFunction")),
+ rParent(rPar)
+{
+}
+/*-- 12.10.00 11:51:48---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+SvxSwAutoCorrCfg::~SvxSwAutoCorrCfg()
+{
+}
+/*-- 12.10.00 11:51:48---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxSwAutoCorrCfg::Commit()
+{
+ Sequence<OUString> aNames = GetPropertyNames();
+
+ Sequence<Any> aValues(aNames.getLength());
+ Any* pValues = aValues.getArray();
+
+ const Type& rType = ::getBooleanCppuType();
+ BOOL bVal;
+ SvxSwAutoFmtFlags& rSwFlags = rParent.pAutoCorrect->GetSwFlags();
+ for(int nProp = 0; nProp < aNames.getLength(); nProp++)
+ {
+ switch(nProp)
+ {
+ case 0: pValues[nProp].setValue(&rParent.bFileRel, rType); break; // "Text/FileLinks",
+ case 1: pValues[nProp].setValue(&rParent.bNetRel, rType); break; // "Text/InternetLinks",
+ case 2: pValues[nProp].setValue(&rParent.bAutoTextPreview, rType); break; // "Text/ShowPreview",
+ case 3: pValues[nProp].setValue(&rParent.bAutoTextTip, rType); break; // "Text/ShowToolTip",
+ case 4: pValues[nProp].setValue(&rParent.bSearchInAllCategories, rType );break; //"Text/SearchInAllCategories"
+ case 5: bVal = rSwFlags.bAutoCorrect; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/UseReplacementTable",
+ case 6: bVal = rSwFlags.bCptlSttSntnc; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/TwoCapitalsAtStart",
+ case 7: bVal = rSwFlags.bCptlSttWrd; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/CapitalAtStartSentence",
+ case 8: bVal = rSwFlags.bChgWeightUnderl; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ChangeUnderlineWeight",
+ case 9: bVal = rSwFlags.bSetINetAttr; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/SetInetAttribute",
+ case 10: bVal = rSwFlags.bChgOrdinalNumber; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ChangeOrdinalNumber",
+ case 11: bVal = rSwFlags.bChgFracionSymbol; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ChangeFraction",
+// it doesn't exist here - the common flags are used for that -> LM
+ case 12:
+ bVal = sal_True; pValues[nProp].setValue(&bVal, rType);
+ break; // "Format/Option/ChangeDash",
+ case 13: bVal = rSwFlags.bDelEmptyNode; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/DelEmptyParagraphs",
+ case 14: bVal = rSwFlags.bChgUserColl; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ReplaceUserStyle",
+ case 15: bVal = rSwFlags.bChgEnumNum; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ChangeToBullets/Enable",
+ case 16:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.cBullet;
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/Char",
+ case 17:
+ pValues[nProp] <<= OUString(rSwFlags.aBulletFont.GetName());
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/Font",
+ case 18:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aBulletFont.GetFamily();
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontFamily",
+ case 19:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aBulletFont.GetCharSet();
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontCharset",
+ case 20:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aBulletFont.GetPitch();
+ break; // "Format/Option/ChangeToBullets/SpecialCharacter/FontPitch",
+ case 21: bVal = rSwFlags.bReplaceQuote; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/ReplaceQuote",
+ case 22: bVal = rSwFlags.bRightMargin; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/CombineParagraphs",
+ case 23:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.nRightMargin;
+ break; // "Format/Option/CombineValue",
+ case 24: bVal = rSwFlags.bAFmtDelSpacesAtSttEnd; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/DelSpacesAtStartEnd",
+ case 25: bVal = rSwFlags.bAFmtDelSpacesBetweenLines; pValues[nProp].setValue(&bVal, rType); break; // "Format/Option/DelSpacesBetween",
+ case 26: bVal = rParent.bAutoFmtByInput; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/Enable",
+ case 27: bVal = rSwFlags.bChgToEnEmDash; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/ChangeDash",
+ case 28: bVal = rSwFlags.bSetNumRule; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/ApplyNumbering/Enable",
+ case 29: bVal = rSwFlags.bSetBorder; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/ChangeToBorders",
+ case 30: bVal = rSwFlags.bCreateTable; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/ChangeToTable",
+ case 31: bVal = rSwFlags.bReplaceStyles; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/ReplaceStyle",
+ case 32: bVal = rSwFlags.bAFmtByInpDelSpacesAtSttEnd; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/DelSpacesAtStartEnd",
+ case 33: bVal = rSwFlags.bAFmtByInpDelSpacesBetweenLines; pValues[nProp].setValue(&bVal, rType); break; // "Format/ByInput/DelSpacesBetween",
+ case 34: bVal = rSwFlags.bAutoCompleteWords; pValues[nProp].setValue(&bVal, rType); break; // "Completion/Enable",
+ case 35:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.nAutoCmpltWordLen;
+ break; // "Completion/MinWordLen",
+ case 36:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.nAutoCmpltListLen;
+ break; // "Completion/MaxListLen",
+ case 37: bVal = rSwFlags.bAutoCmpltCollectWords; pValues[nProp].setValue(&bVal, rType); break; // "Completion/CollectWords",
+ case 38: bVal = rSwFlags.bAutoCmpltEndless; pValues[nProp].setValue(&bVal, rType); break; // "Completion/EndlessList",
+ case 39: bVal = rSwFlags.bAutoCmpltAppendBlanc; pValues[nProp].setValue(&bVal, rType); break; // "Completion/AppendBlank",
+ case 40: bVal = rSwFlags.bAutoCmpltShowAsTip; pValues[nProp].setValue(&bVal, rType); break; // "Completion/ShowAsTip",
+ case 41:
+ pValues[nProp] <<= (sal_Int32)rSwFlags.nAutoCmpltExpandKey;
+ break; // "Completion/AcceptKey"
+ case 42 :bVal = rSwFlags.bAutoCmpltKeepList; pValues[nProp].setValue(&bVal, rType); break;// "Completion/KeepList"
+ case 43 :
+ pValues[nProp] <<= (sal_Int32)rSwFlags.cByInputBullet;
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/Char",
+ case 44 :
+ pValues[nProp] <<= OUString(rSwFlags.aByInputBulletFont.GetName());
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/Font",
+ case 45 :
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aByInputBulletFont.GetFamily();
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontFamily",
+ case 46 :
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aByInputBulletFont.GetCharSet();
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontCharset",
+ case 47 :
+ pValues[nProp] <<= (sal_Int32)rSwFlags.aByInputBulletFont.GetPitch();
+ break;// "Format/ByInput/ApplyNumbering/SpecialCharacter/FontPitch",
+ }
+ }
+ PutProperties(aNames, aValues);
+}
+/*-- 12.10.00 11:51:49---------------------------------------------------
+
+ -----------------------------------------------------------------------*/
+void SvxSwAutoCorrCfg::Notify( const Sequence<OUString>& /* aPropertyNames */ )
+{
+ Load(sal_False);
+}
+
+SvxAutoCorrCfg* SvxAutoCorrCfg::Get()
+{
+ if( !pAutoCorrCfg )
+ pAutoCorrCfg = new SvxAutoCorrCfg;
+ return pAutoCorrCfg;
+}
diff --git a/editeng/source/misc/edtdlg.cxx b/editeng/source/misc/edtdlg.cxx
new file mode 100644
index 0000000000..4f589eee7d
--- /dev/null
+++ b/editeng/source/misc/edtdlg.cxx
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: sfxdlg.cxx,v $
+ * $Revision: 1.7 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <editeng/edtdlg.hxx>
+
+EditAbstractDialogFactory* EditAbstractDialogFactory::Create()
+{
+ return (EditAbstractDialogFactory*) VclAbstractDialogFactory::Create();
+}
diff --git a/editeng/source/misc/forbiddencharacterstable.cxx b/editeng/source/misc/forbiddencharacterstable.cxx
new file mode 100644
index 0000000000..c4d3e158e0
--- /dev/null
+++ b/editeng/source/misc/forbiddencharacterstable.cxx
@@ -0,0 +1,95 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: forbiddencharacterstable.cxx,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <editeng/forbiddencharacterstable.hxx>
+
+#include <unotools/localedatawrapper.hxx>
+#include <editeng/unolingu.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+SvxForbiddenCharactersTable::SvxForbiddenCharactersTable( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMSF, USHORT nISize, USHORT nGrow )
+ : SvxForbiddenCharactersTableImpl( nISize, nGrow )
+{
+ mxMSF = xMSF;
+}
+
+
+SvxForbiddenCharactersTable::~SvxForbiddenCharactersTable()
+{
+ for ( ULONG n = Count(); n; )
+ delete GetObject( --n );
+}
+
+
+
+const com::sun::star::i18n::ForbiddenCharacters* SvxForbiddenCharactersTable::GetForbiddenCharacters( USHORT nLanguage, BOOL bGetDefault ) const
+{
+ ForbiddenCharactersInfo* pInf = Get( nLanguage );
+ if ( !pInf && bGetDefault && mxMSF.is() )
+ {
+ const SvxForbiddenCharactersTableImpl *pConstImpl = dynamic_cast<const SvxForbiddenCharactersTableImpl*>(this);
+ SvxForbiddenCharactersTableImpl* pImpl = const_cast<SvxForbiddenCharactersTableImpl*>(pConstImpl);
+ pInf = new ForbiddenCharactersInfo;
+ pImpl->Insert( nLanguage, pInf );
+
+ pInf->bTemporary = TRUE;
+ LocaleDataWrapper aWrapper( mxMSF, SvxCreateLocale( nLanguage ) );
+ pInf->aForbiddenChars = aWrapper.getForbiddenCharacters();
+ }
+ return pInf ? &pInf->aForbiddenChars : NULL;
+}
+
+
+
+void SvxForbiddenCharactersTable::SetForbiddenCharacters( USHORT nLanguage, const com::sun::star::i18n::ForbiddenCharacters& rForbiddenChars )
+{
+ ForbiddenCharactersInfo* pInf = Get( nLanguage );
+ if ( !pInf )
+ {
+ pInf = new ForbiddenCharactersInfo;
+ Insert( nLanguage, pInf );
+ }
+ pInf->bTemporary = FALSE;
+ pInf->aForbiddenChars = rForbiddenChars;
+}
+
+void SvxForbiddenCharactersTable::ClearForbiddenCharacters( USHORT nLanguage )
+{
+ ForbiddenCharactersInfo* pInf = Get( nLanguage );
+ if ( pInf )
+ {
+ Remove( nLanguage );
+ delete pInf;
+ }
+}
diff --git a/editeng/source/misc/hangulhanja.cxx b/editeng/source/misc/hangulhanja.cxx
new file mode 100644
index 0000000000..7fe2919621
--- /dev/null
+++ b/editeng/source/misc/hangulhanja.cxx
@@ -0,0 +1,1174 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: hangulhanja.cxx,v $
+ * $Revision: 1.20.102.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+#include <editeng/hangulhanja.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/button.hxx>
+#include <unotools/lingucfg.hxx>
+#include <unotools/linguprops.hxx>
+
+#include <set>
+#include <map>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/i18n/ScriptType.hpp>
+#include <com/sun/star/i18n/UnicodeScript.hpp>
+#include <com/sun/star/i18n/XTextConversion.hpp>
+#include <com/sun/star/i18n/XExtendedTextConversion.hpp>
+#include <com/sun/star/i18n/TextConversionType.hpp>
+#include <com/sun/star/i18n/TextConversionOption.hpp>
+#include <com/sun/star/i18n/WordType.hpp>
+#include <vcl/stdtext.hxx>
+#include <unotools/charclass.hxx>
+
+#include <editeng/edtdlg.hxx>
+#include <editeng/editrids.hrc>
+#include <editeng/unolingu.hxx>
+
+#define HHC HangulHanjaConversion
+
+//.............................................................................
+namespace editeng
+{
+//.............................................................................
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::i18n;
+ using namespace ::com::sun::star::i18n::TextConversionOption;
+ using namespace ::com::sun::star::i18n::TextConversionType;
+ using namespace ::com::sun::star::lang;
+/*
+ using HangulHanjaConversion::ReplacementAction;
+ using HangulHanjaConversion::eExchange;
+ using HangulHanjaConversion::eReplacementBracketed;
+ using HangulHanjaConversion::eOriginalBracketed;
+ using HangulHanjaConversion::eReplacementAbove;
+ using HangulHanjaConversion::eOriginalAbove;
+ using HangulHanjaConversion::eReplacementBelow;
+ using HangulHanjaConversion::eOriginalBelow;
+
+ using HangulHanjaConversion::eHangulToHanja;
+ using HangulHanjaConversion::eHanjaToHangul;
+
+ using HangulHanjaConversion::eSimpleConversion;
+ using HangulHanjaConversion::eHangulBracketed;
+ using HangulHanjaConversion::eHanjaBracketed;
+ using HangulHanjaConversion::eRubyHanjaAbove;
+ using HangulHanjaConversion::eRubyHanjaBelow;
+ using HangulHanjaConversion::eRubyHangulAbove;
+ using HangulHanjaConversion::eRubyHangulBelow;
+
+ using ::com::sun::star::i18n::TextConversionType::TO_HANJA;
+ using ::com::sun::star::i18n::TextConversionType::TO_HANGUL;
+ using ::com::sun::star::i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
+ using ::com::sun::star::i18n::TextConversionOption::NONE;
+*/
+ //=========================================================================
+ //= HangulHanjaConversion_Impl
+ //=========================================================================
+ //using HangulHanjaConversion::ConversionFormat;
+
+ class HangulHanjaConversion_Impl
+ {
+ private:
+ typedef ::std::set< ::rtl::OUString, ::std::less< ::rtl::OUString > > StringBag;
+ typedef ::std::map< ::rtl::OUString, ::rtl::OUString, ::std::less< ::rtl::OUString > > StringMap;
+
+ private:
+ StringBag m_sIgnoreList;
+ StringMap m_aChangeList;
+ static StringMap m_aRecentlyUsedList;
+
+ // general
+ AbstractHangulHanjaConversionDialog* //CHINA001 HangulHanjaConversionDialog*
+ m_pConversionDialog; // the dialog to display for user interaction
+ Window* m_pUIParent; // the parent window for any UI we raise
+ Reference< XMultiServiceFactory >
+ m_xORB; // the service factory to use
+ Reference< XTextConversion >
+ m_xConverter; // the text conversion service
+ Locale m_aSourceLocale; // the locale we're working with
+
+ // additions for Chinese simplified / traditional conversion
+ HHC::ConversionType m_eConvType; // conversion type (Hangul/Hanja, simplified/traditional Chinese,...)
+ LanguageType m_nSourceLang; // just a 'copy' of m_aSourceLocale in order in order to
+ // save the applications from always converting to this
+ // type in their implementations
+ LanguageType m_nTargetLang; // target language of new replacement text
+ const Font* m_pTargetFont; // target font of new replacement text
+ sal_Int32 m_nConvOptions; // text conversion options (as used by 'getConversions')
+ sal_Bool m_bIsInteractive; // specifies if the conversion requires user interaction
+ // (and likeley a specialised dialog) or if it is to run
+ // automatically without any user interaction.
+ // True for Hangul / Hanja conversion
+ // False for Chinese simlified / traditional conversion
+
+ HangulHanjaConversion* m_pAntiImpl; // our "anti-impl" instance
+
+ // options
+ sal_Bool m_bByCharacter; // are we in "by character" mode currently?
+ HHC::ConversionFormat m_eConversionFormat; // the current format for the conversion
+ HHC::ConversionDirection m_ePrimaryConversionDirection; // the primary conversion direction
+ HHC::ConversionDirection m_eCurrentConversionDirection; // the primary conversion direction
+
+ //options from Hangul/Hanja Options dialog (also saved to configuration)
+ bool m_bIgnorePostPositionalWord;
+ bool m_bShowRecentlyUsedFirst;
+ bool m_bAutoReplaceUnique;
+
+ // state
+ ::rtl::OUString m_sCurrentPortion; // the text which we are currently working on
+ LanguageType m_nCurrentPortionLang; // language of m_sCurrentPortion found
+ sal_Int32 m_nCurrentStartIndex; // the start index within m_sCurrentPortion of the current convertible portion
+ sal_Int32 m_nCurrentEndIndex; // the end index (excluding) within m_sCurrentPortion of the current convertible portion
+ sal_Int32 m_nReplacementBaseIndex;// index which ReplaceUnit-calls need to be relative to
+ sal_Int32 m_nCurrentConversionOption;
+ sal_Int16 m_nCurrentConversionType;
+ Sequence< ::rtl::OUString >
+ m_aCurrentSuggestions; // the suggestions for the current unit
+ // (means for the text [m_nCurrentStartIndex, m_nCurrentEndIndex) in m_sCurrentPortion)
+ sal_Bool m_bTryBothDirections; // specifies if other conversion directions should be tried when looking for convertible characters
+
+
+ public:
+ HangulHanjaConversion_Impl(
+ Window* _pUIParent,
+ const Reference< XMultiServiceFactory >& _rxORB,
+ const Locale& _rSourceLocale,
+ const Locale& _rTargetLocale,
+ const Font* _pTargetFont,
+ sal_Int32 _nConvOptions,
+ sal_Bool _bIsInteractive,
+ HangulHanjaConversion* _pAntiImpl );
+
+ public:
+
+ static void SetUseSavedConversionDirectionState( sal_Bool bVal );
+
+ void DoDocumentConversion( );
+
+ inline sal_Bool IsByCharacter( ) const { return m_bByCharacter; }
+
+ inline sal_Bool IsValid() const { return m_xConverter.is(); }
+
+ inline LanguageType GetSourceLang() const { return m_nSourceLang; }
+ inline LanguageType GetTargetLang() const { return m_nTargetLang; }
+ inline const Font * GetTargetFont() const { return m_pTargetFont; }
+ inline sal_Int32 GetConvOptions() const { return m_nConvOptions; }
+ inline sal_Bool IsInteractive() const { return m_bIsInteractive; }
+
+ protected:
+ void createDialog();
+
+ /** continue with the conversion, return <TRUE/> if and only if the complete conversion is done
+ @param _bRepeatCurrentUnit
+ if <TRUE/>, an implNextConvertible will be called initially to advance to the next convertible.
+ if <FALSE/>, the method will initially work with the current convertible unit
+ */
+ sal_Bool ContinueConversion( bool _bRepeatCurrentUnit );
+
+ private:
+ DECL_LINK( OnOptionsChanged, void* );
+ DECL_LINK( OnIgnore, void* );
+ DECL_LINK( OnIgnoreAll, void* );
+ DECL_LINK( OnChange, void* );
+ DECL_LINK( OnChangeAll, void* );
+ DECL_LINK( OnByCharClicked, CheckBox* );
+ DECL_LINK( OnConversionTypeChanged, void* );
+ DECL_LINK( OnFind, void* );
+
+ /** proceed, after the current convertible has been handled
+
+ <p><b>Attention:</b>
+ When returning from this method, the dialog may have been deleted!</p>
+
+ @param _bRepeatCurrentUnit
+ will be passed to the <member>ContinueConversion</member> call
+ */
+ void implProceed( bool _bRepeatCurrentUnit );
+
+ // change the current convertible, and do _not_ proceed
+ void implChange( const ::rtl::OUString& _rChangeInto );
+
+ /** find the next convertible piece of text, with possibly advancing to the next portion
+
+ @see HangulHanjaConversion::GetNextPortion
+ */
+ sal_Bool implNextConvertible( bool _bRepeatUnit );
+
+ /** find the next convertible unit within the current portion
+ @param _bRepeatUnit
+ if <TRUE/>, the search will start at the beginning of the current unit,
+ if <FALSE/>, it will start at the end of the current unit
+ */
+ bool implNextConvertibleUnit( const sal_Int32 _nStartAt );
+
+ /** retrieves the next portion, with setting the index members properly
+ @return
+ <TRUE/> if and only if there is a next portion
+ */
+ bool implRetrieveNextPortion( );
+
+ /** determine the ConversionDirection for m_sCurrentPortion
+ @return
+ <FALSE/> if and only if something went wrong
+ */
+ bool implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection& rDirection );
+
+ /** member m_aCurrentSuggestions and m_nCurrentEndIndex are updated according to the other settings and current dictionaries
+
+ if _bAllowSearchNextConvertibleText is true _nStartAt is used as starting point to search the next
+ convertible text portion. This may result in changing of the member m_nCurrentStartIndex additionally.
+
+ @return
+ <TRUE/> if Suggestions were found
+ */
+ bool implUpdateSuggestions( const bool _bAllowSearchNextConvertibleText=false, const sal_Int32 _nStartAt=-1 );
+
+ /** reads the options from Hangul/Hanja Options dialog that are saved to configuration
+ */
+ void implReadOptionsFromConfiguration();
+
+ /** get the string currently considered to be replaced or ignored
+ */
+ ::rtl::OUString GetCurrentUnit() const;
+
+ /** read options from configuration, update suggestion list and dialog content
+ */
+ void implUpdateData();
+
+ /** get the conversion direction dependent from m_eConvType and m_eCurrentConversionDirection
+ in case of switching the direction is allowed this can be triggered with parameter bSwitchDirection
+ */
+ sal_Int16 implGetConversionType( bool bSwitchDirection=false ) const;
+ };
+
+ //=========================================================================
+ //= HangulHanjaConversion_Impl
+ //=========================================================================
+ //-------------------------------------------------------------------------
+ // static member initialization
+ HangulHanjaConversion_Impl::StringMap HangulHanjaConversion_Impl::m_aRecentlyUsedList = HangulHanjaConversion_Impl::StringMap();
+
+ //-------------------------------------------------------------------------
+ HangulHanjaConversion_Impl::HangulHanjaConversion_Impl( Window* _pUIParent,
+ const Reference< XMultiServiceFactory >& _rxORB,
+ const Locale& _rSourceLocale,
+ const Locale& _rTargetLocale,
+ const Font* _pTargetFont,
+ sal_Int32 _nOptions,
+ sal_Bool _bIsInteractive,
+ HangulHanjaConversion* _pAntiImpl )
+: m_pConversionDialog( NULL )
+, m_pUIParent( _pUIParent )
+, m_xORB( _rxORB )
+, m_aSourceLocale( _rSourceLocale )
+, m_nSourceLang( SvxLocaleToLanguage( _rSourceLocale ) )
+, m_nTargetLang( SvxLocaleToLanguage( _rTargetLocale ) )
+, m_pTargetFont( _pTargetFont )
+, m_bIsInteractive( _bIsInteractive )
+, m_pAntiImpl( _pAntiImpl )
+, m_nCurrentPortionLang( LANGUAGE_NONE )
+, m_nCurrentStartIndex( 0 )
+, m_nCurrentEndIndex( 0 )
+, m_nReplacementBaseIndex( 0 )
+, m_nCurrentConversionOption( TextConversionOption::NONE )
+, m_nCurrentConversionType( -1 ) // not yet known
+, m_bTryBothDirections( sal_True )
+ {
+ implReadOptionsFromConfiguration();
+
+ DBG_ASSERT( m_xORB.is(), "HangulHanjaConversion_Impl::HangulHanjaConversion_Impl: no ORB!" );
+
+ // determine conversion type
+ if (m_nSourceLang == LANGUAGE_KOREAN && m_nTargetLang == LANGUAGE_KOREAN)
+ m_eConvType = HHC::eConvHangulHanja;
+ else if ( (m_nSourceLang == LANGUAGE_CHINESE_TRADITIONAL && m_nTargetLang == LANGUAGE_CHINESE_SIMPLIFIED) ||
+ (m_nSourceLang == LANGUAGE_CHINESE_SIMPLIFIED && m_nTargetLang == LANGUAGE_CHINESE_TRADITIONAL) )
+ m_eConvType = HHC::eConvSimplifiedTraditional;
+ else
+ {
+ DBG_ERROR( "failed to determine conversion type from languages" );
+ }
+
+ // set remaining conversion parameters to their default values
+ m_nConvOptions = _nOptions;
+ m_bByCharacter = 0 != (_nOptions & CHARACTER_BY_CHARACTER);
+ m_eConversionFormat = HHC::eSimpleConversion;
+ m_ePrimaryConversionDirection = HHC::eHangulToHanja; // used for eConvHangulHanja
+ m_eCurrentConversionDirection = HHC::eHangulToHanja; // used for eConvHangulHanja
+
+ if ( m_xORB.is() )
+ {
+ ::rtl::OUString sTextConversionService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.TextConversion" ) );
+ m_xConverter = m_xConverter.query( m_xORB->createInstance( sTextConversionService ) );
+ if ( !m_xConverter.is() )
+ ShowServiceNotAvailableError( m_pUIParent, sTextConversionService, sal_True );
+ }
+
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::createDialog()
+ {
+ DBG_ASSERT( m_bIsInteractive, "createDialog when the conversion should not be interactive?" );
+ if ( m_bIsInteractive && !m_pConversionDialog )
+ {
+ EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
+ if(pFact)
+ {
+ m_pConversionDialog = pFact->CreateHangulHanjaConversionDialog(m_pUIParent, m_ePrimaryConversionDirection );
+ DBG_ASSERT(m_pConversionDialog, "Dialogdiet fail!");//CHINA001
+
+ m_pConversionDialog->EnableRubySupport( m_pAntiImpl->HasRubySupport() );
+
+ m_pConversionDialog->SetByCharacter( m_bByCharacter );
+ m_pConversionDialog->SetConversionFormat( m_eConversionFormat );
+ m_pConversionDialog->SetConversionDirectionState( m_bTryBothDirections, m_ePrimaryConversionDirection );
+
+ // the handlers
+ m_pConversionDialog->SetOptionsChangedHdl( LINK( this, HangulHanjaConversion_Impl, OnOptionsChanged ) );
+ m_pConversionDialog->SetIgnoreHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnore ) );
+ m_pConversionDialog->SetIgnoreAllHdl( LINK( this, HangulHanjaConversion_Impl, OnIgnoreAll ) );
+ m_pConversionDialog->SetChangeHdl( LINK( this, HangulHanjaConversion_Impl, OnChange ) );
+ m_pConversionDialog->SetChangeAllHdl( LINK( this, HangulHanjaConversion_Impl, OnChangeAll ) );
+ m_pConversionDialog->SetClickByCharacterHdl( LINK( this, HangulHanjaConversion_Impl, OnByCharClicked ) );
+ m_pConversionDialog->SetConversionFormatChangedHdl( LINK( this, HangulHanjaConversion_Impl, OnConversionTypeChanged ) );
+ m_pConversionDialog->SetFindHdl( LINK( this, HangulHanjaConversion_Impl, OnFind ) );
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Int16 HangulHanjaConversion_Impl::implGetConversionType( bool bSwitchDirection ) const
+ {
+ sal_Int16 nConversionType = -1;
+ if (m_eConvType == HHC::eConvHangulHanja)
+ nConversionType = HHC::eHangulToHanja == ( m_eCurrentConversionDirection && !bSwitchDirection ) ? TO_HANJA : TO_HANGUL;
+ else if (m_eConvType == HHC::eConvSimplifiedTraditional)
+ nConversionType = LANGUAGE_CHINESE_SIMPLIFIED == m_nTargetLang ? TO_SCHINESE : TO_TCHINESE;
+ DBG_ASSERT( nConversionType != -1, "unexpected conversion type" );
+ return nConversionType;
+ }
+
+ //-------------------------------------------------------------------------
+ bool HangulHanjaConversion_Impl::implUpdateSuggestions( bool _bAllowSearchNextConvertibleText, const sal_Int32 _nStartAt )
+ {
+ // parameters for the converter
+ sal_Int32 nStartSearch = m_nCurrentStartIndex;
+ if( _bAllowSearchNextConvertibleText )
+ nStartSearch = _nStartAt;
+
+ sal_Int32 nLength = m_sCurrentPortion.getLength() - nStartSearch;
+ m_nCurrentConversionType = implGetConversionType();
+ m_nCurrentConversionOption = IsByCharacter() ? CHARACTER_BY_CHARACTER : NONE;
+ if( m_bIgnorePostPositionalWord )
+ m_nCurrentConversionOption = m_nCurrentConversionOption | IGNORE_POST_POSITIONAL_WORD;
+
+ // no need to check both directions for chinese conversion (saves time)
+ if (m_eConvType == HHC::eConvSimplifiedTraditional)
+ m_bTryBothDirections = sal_False;
+
+ sal_Bool bFoundAny = sal_True;
+ try
+ {
+ TextConversionResult aResult = m_xConverter->getConversions(
+ m_sCurrentPortion,
+ nStartSearch,
+ nLength,
+ m_aSourceLocale,
+ m_nCurrentConversionType,
+ m_nCurrentConversionOption
+ );
+ sal_Bool bFoundPrimary = aResult.Boundary.startPos < aResult.Boundary.endPos;
+ bFoundAny = bFoundPrimary;
+
+ if ( m_bTryBothDirections )
+ { // see if we find another convertible when assuming the other direction
+ TextConversionResult aSecondResult = m_xConverter->getConversions(
+ m_sCurrentPortion,
+ nStartSearch,
+ nLength,
+ m_aSourceLocale,
+ implGetConversionType( true ), // switched!
+ m_nCurrentConversionOption
+ );
+ if ( aSecondResult.Boundary.startPos < aSecondResult.Boundary.endPos )
+ { // we indeed found such a convertible
+
+ // in case the first attempt (with the original conversion direction)
+ // didn't find anything
+ if ( !bFoundPrimary
+ // or if the second location is _before_ the first one
+ || ( aSecondResult.Boundary.startPos < aResult.Boundary.startPos )
+ )
+ {
+ // then use the second finding
+ aResult = aSecondResult;
+
+ // our current conversion direction changed now
+ m_eCurrentConversionDirection = ( HHC::eHangulToHanja == m_eCurrentConversionDirection )
+ ? HHC::eHanjaToHangul : HHC::eHangulToHanja;
+ bFoundAny = sal_True;
+ }
+ }
+ }
+
+ if( _bAllowSearchNextConvertibleText )
+ {
+ //this might change the current position
+ m_aCurrentSuggestions = aResult.Candidates;
+ m_nCurrentStartIndex = aResult.Boundary.startPos;
+ m_nCurrentEndIndex = aResult.Boundary.endPos;
+ }
+ else
+ {
+ //the change of starting position is not allowed
+ if( m_nCurrentStartIndex == aResult.Boundary.startPos
+ && aResult.Boundary.endPos != aResult.Boundary.startPos )
+ {
+ m_aCurrentSuggestions = aResult.Candidates;
+ m_nCurrentEndIndex = aResult.Boundary.endPos;
+ }
+ else
+ {
+ m_aCurrentSuggestions.realloc( 0 );
+ if( m_sCurrentPortion.getLength() >= m_nCurrentStartIndex+1 )
+ m_nCurrentEndIndex = m_nCurrentStartIndex+1;
+ }
+ }
+
+ //put recently used string to front:
+ if( m_bShowRecentlyUsedFirst && m_aCurrentSuggestions.getLength()>1 )
+ {
+ ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
+ StringMap::const_iterator aRecentlyUsed = m_aRecentlyUsedList.find( sCurrentUnit );
+ bool bUsedBefore = aRecentlyUsed != m_aRecentlyUsedList.end();
+ if( bUsedBefore && m_aCurrentSuggestions[0] != aRecentlyUsed->second )
+ {
+ sal_Int32 nCount = m_aCurrentSuggestions.getLength();
+ Sequence< ::rtl::OUString > aTmp(nCount);
+ aTmp[0]=aRecentlyUsed->second;
+ sal_Int32 nDiff = 1;
+ for( sal_Int32 n=1; n<nCount; n++)//we had 0 already
+ {
+ if( nDiff && m_aCurrentSuggestions[n-nDiff]==aRecentlyUsed->second )
+ nDiff=0;
+ aTmp[n]=m_aCurrentSuggestions[n-nDiff];
+ }
+ m_aCurrentSuggestions = aTmp;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "HangulHanjaConversion_Impl::implNextConvertibleUnit: caught an exception!" );
+
+ //!!! at least we want to move on in the text in order
+ //!!! to avoid an endless loop...
+ return false;
+ }
+ return bFoundAny;
+ }
+
+ //-------------------------------------------------------------------------
+ bool HangulHanjaConversion_Impl::implNextConvertibleUnit( const sal_Int32 _nStartAt )
+ {
+ m_aCurrentSuggestions.realloc( 0 );
+
+ // ask the TextConversion service for the next convertible piece of text
+
+ // get current values from dialog
+ if( m_eConvType == HHC::eConvHangulHanja && m_pConversionDialog )
+ {
+ m_bTryBothDirections = m_pConversionDialog->GetUseBothDirections();
+ HHC::ConversionDirection eDialogDirection = HHC::eHangulToHanja;
+ eDialogDirection = m_pConversionDialog->GetDirection( eDialogDirection );
+
+ if( !m_bTryBothDirections && eDialogDirection != m_eCurrentConversionDirection )
+ {
+ m_eCurrentConversionDirection = eDialogDirection;
+ }
+
+ // save curently used value for possible later use
+ m_pAntiImpl->m_bTryBothDirectionsSave = m_bTryBothDirections;
+ m_pAntiImpl->m_ePrimaryConversionDirectionSave = m_eCurrentConversionDirection;
+ }
+
+ bool bFoundAny = implUpdateSuggestions( true, _nStartAt );
+
+ return bFoundAny &&
+ (m_nCurrentStartIndex < m_sCurrentPortion.getLength());
+ }
+
+ //-------------------------------------------------------------------------
+ bool HangulHanjaConversion_Impl::implRetrieveNextPortion( )
+ {
+ sal_Bool bAllowImplicitChanges = m_eConvType == HHC::eConvSimplifiedTraditional;
+
+ m_sCurrentPortion = ::rtl::OUString();
+ m_nCurrentPortionLang = LANGUAGE_NONE;
+ m_pAntiImpl->GetNextPortion( m_sCurrentPortion, m_nCurrentPortionLang, bAllowImplicitChanges );
+ m_nReplacementBaseIndex = 0;
+ m_nCurrentStartIndex = m_nCurrentEndIndex = 0;
+
+ bool bRet = 0 != m_sCurrentPortion.getLength();
+
+ if (m_eConvType == HHC::eConvHangulHanja && m_bTryBothDirections)
+ implGetConversionDirectionForCurrentPortion( m_eCurrentConversionDirection );
+
+ return bRet;
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Bool HangulHanjaConversion_Impl::implNextConvertible( bool _bRepeatUnit )
+ {
+ if ( _bRepeatUnit || ( m_nCurrentEndIndex < m_sCurrentPortion.getLength() ) )
+ {
+ if ( implNextConvertibleUnit(
+ _bRepeatUnit
+ ? ( IsByCharacter() ? m_nCurrentStartIndex : m_nCurrentStartIndex )
+ : m_nCurrentEndIndex
+ ) )
+ return sal_True;
+ }
+
+ // no convertible text in the current portion anymore
+ // -> advance to the next portion
+ do
+ {
+ // next portion
+ if ( implRetrieveNextPortion( ) )
+ { // there is a next portion
+ // -> find the next convertible unit in the current portion
+ if ( implNextConvertibleUnit( 0 ) )
+ return sal_True;
+ }
+ }
+ while ( m_sCurrentPortion.getLength() );
+
+ // no more portions
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------
+ ::rtl::OUString HangulHanjaConversion_Impl::GetCurrentUnit() const
+ {
+ DBG_ASSERT( m_nCurrentStartIndex < m_sCurrentPortion.getLength(),
+ "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
+ DBG_ASSERT( m_nCurrentEndIndex <= m_sCurrentPortion.getLength(),
+ "HangulHanjaConversion_Impl::GetCurrentUnit: invalid index into current portion!" );
+ DBG_ASSERT( m_nCurrentStartIndex <= m_nCurrentEndIndex,
+ "HangulHanjaConversion_Impl::GetCurrentUnit: invalid interval!" );
+
+ ::rtl::OUString sCurrentUnit = m_sCurrentPortion.copy( m_nCurrentStartIndex, m_nCurrentEndIndex - m_nCurrentStartIndex );
+ return sCurrentUnit;
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Bool HangulHanjaConversion_Impl::ContinueConversion( bool _bRepeatCurrentUnit )
+ {
+ sal_Bool bNeedUserInteraction = sal_False; // when we leave here, do we need user interaction?
+ sal_Bool bDocumentDone = sal_False; // did we already check the whole document?
+
+ while ( !bDocumentDone && !bNeedUserInteraction && implNextConvertible( _bRepeatCurrentUnit ) )
+ {
+ ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
+
+ // do we need to ignore it?
+ sal_Bool bAlwaysIgnoreThis = m_sIgnoreList.end() != m_sIgnoreList.find( sCurrentUnit );
+
+ // do we need to change it?
+ StringMap::const_iterator aChangeListPos = m_aChangeList.find( sCurrentUnit );
+ sal_Bool bAlwaysChangeThis = m_aChangeList.end() != aChangeListPos;
+
+ // do we automatically change this?
+ sal_Bool bAutoChange = m_bAutoReplaceUnique && m_aCurrentSuggestions.getLength() == 1;
+
+ if (!m_bIsInteractive)
+ {
+ // silent conversion (e.g. for simplified/traditional Chinese)...
+ if(m_aCurrentSuggestions.getLength()>0)
+ implChange( m_aCurrentSuggestions.getConstArray()[0] );
+ }
+ else if (bAutoChange)
+ {
+ implChange( m_aCurrentSuggestions.getConstArray()[0] );
+ }
+ else if ( bAlwaysChangeThis )
+ {
+ implChange( aChangeListPos->second );
+ }
+ else if ( !bAlwaysIgnoreThis )
+ {
+ // here we need to ask the user for what to do with the text
+ // for this, allow derivees to highlight the current text unit in a possible document view
+ m_pAntiImpl->HandleNewUnit( m_nCurrentStartIndex - m_nReplacementBaseIndex, m_nCurrentEndIndex - m_nReplacementBaseIndex );
+
+ DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
+ if( m_pConversionDialog )
+ m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions );
+
+ // do not look for the next convertible: We have to wait for the user to interactivly
+ // decide what happens with the current convertible
+ bNeedUserInteraction = sal_True;
+ }
+ }
+
+ /*
+ if ( bDocumentDone )
+ return sal_True; // we explicitly know that the complete document is done
+ else if ( bNeedUserInteraction )
+ return sal_False; // the doc is not done, we found a convertible, but need the user to decide
+ else
+ return sal_True; // we did not find a next convertible, so the document is implicitly done
+ */
+
+ return bDocumentDone || !bNeedUserInteraction;
+ }
+
+ //-------------------------------------------------------------------------
+ bool HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion( HHC::ConversionDirection& rDirection )
+ {
+ // - For eConvHangulHanja the direction is determined by
+ // the first encountered Korean character.
+ // - For eConvSimplifiedTraditional the conversion direction
+ // is already specified by the source language.
+
+ bool bSuccess = true;
+
+ if (m_eConvType == HHC::eConvHangulHanja)
+ {
+ bSuccess = false;
+ try
+ {
+ // get the break iterator service
+ ::rtl::OUString sBreakIteratorService( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" ) );
+ Reference< XInterface > xBI( m_xORB->createInstance( ::rtl::OUString( sBreakIteratorService ) ) );
+ Reference< XBreakIterator > xBreakIter( xBI, UNO_QUERY );
+ if ( !xBreakIter.is() )
+ {
+ ShowServiceNotAvailableError( m_pUIParent, sBreakIteratorService, sal_True );
+ }
+ else
+ {
+ sal_Int32 nNextAsianScript = xBreakIter->beginOfScript( m_sCurrentPortion, m_nCurrentStartIndex, com::sun::star::i18n::ScriptType::ASIAN );
+ if ( -1 == nNextAsianScript )
+ nNextAsianScript = xBreakIter->nextScript( m_sCurrentPortion, m_nCurrentStartIndex, com::sun::star::i18n::ScriptType::ASIAN );
+ if ( ( nNextAsianScript >= m_nCurrentStartIndex ) && ( nNextAsianScript < m_sCurrentPortion.getLength() ) )
+ { // found asian text
+
+ // determine if it's Hangul
+ CharClass aCharClassificaton( m_xORB, m_aSourceLocale );
+ sal_Int16 nScript = aCharClassificaton.getScript( m_sCurrentPortion, sal::static_int_cast< USHORT >(nNextAsianScript) );
+ if ( ( UnicodeScript_kHangulJamo == nScript )
+ || ( UnicodeScript_kHangulCompatibilityJamo == nScript )
+ || ( UnicodeScript_kHangulSyllable == nScript )
+ )
+ {
+ rDirection = HHC::eHangulToHanja;
+ }
+ else
+ {
+ rDirection = HHC::eHanjaToHangul;
+ }
+
+ bSuccess = true;
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "HangulHanjaConversion_Impl::implGetConversionDirectionForCurrentPortion: caught an exception!" );
+ }
+ }
+
+ return bSuccess;
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::DoDocumentConversion( )
+ {
+ // clear the change-all list - it's to be re-initialized for every single document
+ {
+ StringMap aEmpty;
+ m_aChangeList.swap( aEmpty );
+ }
+
+ // first of all, we need to guess the direction of our conversion - it is determined by the first
+ // hangul or hanja character in the first text
+ if ( !implRetrieveNextPortion() )
+ {
+ DBG_WARNING( "HangulHanjaConversion_Impl::DoDocumentConversion: why did you call me if you do have nothing to convert?" );
+ // nothing to do
+ return;
+ }
+ if( m_eConvType == HHC::eConvHangulHanja )
+ {
+ //init conversion direction from saved value
+ HHC::ConversionDirection eDirection = HHC::eHangulToHanja;
+ if(!implGetConversionDirectionForCurrentPortion( eDirection ))
+ // something went wrong, has already been asserted
+ return;
+
+ if (m_pAntiImpl->IsUseSavedConversionDirectionState())
+ {
+ m_ePrimaryConversionDirection = m_pAntiImpl->m_ePrimaryConversionDirectionSave;
+ m_bTryBothDirections = m_pAntiImpl->m_bTryBothDirectionsSave;
+ if( m_bTryBothDirections )
+ m_eCurrentConversionDirection = eDirection;
+ else
+ m_eCurrentConversionDirection = m_ePrimaryConversionDirection;
+ }
+ else
+ {
+ m_ePrimaryConversionDirection = eDirection;
+ m_eCurrentConversionDirection = eDirection;
+ }
+ }
+
+ if (m_bIsInteractive && m_eConvType == HHC::eConvHangulHanja)
+ {
+ //always open dialog if at least having a hangul or hanja text portion
+ createDialog();
+ if(m_pAntiImpl->IsUseSavedConversionDirectionState())
+ ContinueConversion( sal_False );
+ else
+ implUpdateData();
+ m_pConversionDialog->Execute();
+ DELETEZ( m_pConversionDialog );
+ }
+ else
+ {
+#ifdef DBG_UTIL
+ sal_Bool bCompletelyDone =
+#endif
+ ContinueConversion( sal_False );
+ DBG_ASSERT( bCompletelyDone, "HangulHanjaConversion_Impl::DoDocumentConversion: ContinueConversion should have returned true here!" );
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::implProceed( bool _bRepeatCurrentUnit )
+ {
+ if ( ContinueConversion( _bRepeatCurrentUnit ) )
+ { // we're done with the whole document
+ DBG_ASSERT( !m_bIsInteractive || m_pConversionDialog, "HangulHanjaConversion_Impl::implProceed: we should not reach this here without dialog!" );
+ if ( m_pConversionDialog )
+ m_pConversionDialog->EndDialog( RET_OK );
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::implChange( const ::rtl::OUString& _rChangeInto )
+ {
+ if( !_rChangeInto.getLength() )
+ return;
+
+ // translate the conversion format into a replacement action
+ // this translation depends on whether we have a Hangul original, or a Hanja original
+
+ HHC::ReplacementAction eAction( HHC::eExchange );
+
+ if (m_eConvType == HHC::eConvHangulHanja)
+ {
+ // is the original we're about to change in Hangul?
+ sal_Bool bOriginalIsHangul = HHC::eHangulToHanja == m_eCurrentConversionDirection;
+
+ switch ( m_eConversionFormat )
+ {
+ case HHC::eSimpleConversion: eAction = HHC::eExchange; break;
+ case HHC::eHangulBracketed: eAction = bOriginalIsHangul ? HHC::eOriginalBracketed : HHC::eReplacementBracketed; break;
+ case HHC::eHanjaBracketed: eAction = bOriginalIsHangul ? HHC::eReplacementBracketed : HHC::eOriginalBracketed; break;
+ case HHC::eRubyHanjaAbove: eAction = bOriginalIsHangul ? HHC::eReplacementAbove : HHC::eOriginalAbove; break;
+ case HHC::eRubyHanjaBelow: eAction = bOriginalIsHangul ? HHC::eReplacementBelow : HHC::eOriginalBelow; break;
+ case HHC::eRubyHangulAbove: eAction = bOriginalIsHangul ? HHC::eOriginalAbove : HHC::eReplacementAbove; break;
+ case HHC::eRubyHangulBelow: eAction = bOriginalIsHangul ? HHC::eOriginalBelow : HHC::eReplacementBelow; break;
+ default:
+ DBG_ERROR( "HangulHanjaConversion_Impl::implChange: invalid/unexpected conversion format!" );
+ }
+ }
+
+ // the proper indicies (the wrapper implementation needs indicies relative to the
+ // previous replacement)
+ DBG_ASSERT( ( m_nReplacementBaseIndex <= m_nCurrentStartIndex ) && ( m_nReplacementBaseIndex <= m_nCurrentEndIndex ),
+ "HangulHanjaConversion_Impl::implChange: invalid replacement base!" );
+
+ sal_Int32 nStartIndex = m_nCurrentStartIndex - m_nReplacementBaseIndex;
+ sal_Int32 nEndIndex = m_nCurrentEndIndex - m_nReplacementBaseIndex;
+
+ //remind this decision
+ m_aRecentlyUsedList[ GetCurrentUnit() ] = _rChangeInto;
+
+ LanguageType *pNewUnitLang = 0;
+ LanguageType nNewUnitLang = LANGUAGE_NONE;
+ if (m_eConvType == HHC::eConvSimplifiedTraditional)
+ {
+ // check if language needs to be changed
+ if ( m_pAntiImpl->GetTargetLanguage() == LANGUAGE_CHINESE_TRADITIONAL &&
+ !m_pAntiImpl->IsTraditional( m_nCurrentPortionLang ))
+ nNewUnitLang = LANGUAGE_CHINESE_TRADITIONAL;
+ else if ( m_pAntiImpl->GetTargetLanguage() == LANGUAGE_CHINESE_SIMPLIFIED &&
+ !m_pAntiImpl->IsSimplified( m_nCurrentPortionLang ))
+ nNewUnitLang = LANGUAGE_CHINESE_SIMPLIFIED;
+ if (nNewUnitLang != LANGUAGE_NONE)
+ pNewUnitLang = &nNewUnitLang;
+ }
+
+ // according to FT we should not (yet) bother about Hangul/Hanja conversion here
+ //
+ // aOffsets is needed in ReplaceUnit below in order to to find out
+ // exactly which characters are really changed in order to keep as much
+ // from attributation for the text as possible.
+ Sequence< sal_Int32 > aOffsets;
+ Reference< XExtendedTextConversion > xExtConverter( m_xConverter, UNO_QUERY );
+ if (m_eConvType == HHC::eConvSimplifiedTraditional && xExtConverter.is())
+ {
+ try
+ {
+ ::rtl::OUString aConvText = xExtConverter->getConversionWithOffset(
+ m_sCurrentPortion,
+ m_nCurrentStartIndex,
+ m_nCurrentEndIndex - m_nCurrentStartIndex,
+ m_aSourceLocale,
+ m_nCurrentConversionType,
+ m_nCurrentConversionOption,
+ aOffsets
+ );
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "HangulHanjaConversion_Impl::implChange: caught unexpected exception!" );
+ aOffsets.realloc(0);
+ }
+ }
+
+ // do the replacement
+ m_pAntiImpl->ReplaceUnit( nStartIndex, nEndIndex, m_sCurrentPortion,
+ _rChangeInto, aOffsets, eAction, pNewUnitLang );
+
+
+ // adjust the replacement base
+ m_nReplacementBaseIndex = m_nCurrentEndIndex;
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::implReadOptionsFromConfiguration()
+ {
+ SvtLinguConfig aLngCfg;
+ aLngCfg.GetProperty( UPH_IS_IGNORE_POST_POSITIONAL_WORD ) >>= m_bIgnorePostPositionalWord;
+ aLngCfg.GetProperty( UPH_IS_SHOW_ENTRIES_RECENTLY_USED_FIRST ) >>= m_bShowRecentlyUsedFirst;
+ aLngCfg.GetProperty( UPH_IS_AUTO_REPLACE_UNIQUE_ENTRIES ) >>= m_bAutoReplaceUnique;
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion_Impl::implUpdateData()
+ {
+ implReadOptionsFromConfiguration();
+ implUpdateSuggestions();
+
+ if(m_pConversionDialog)
+ {
+ ::rtl::OUString sCurrentUnit( GetCurrentUnit() );
+
+ m_pConversionDialog->SetCurrentString( sCurrentUnit, m_aCurrentSuggestions );
+ m_pConversionDialog->FocusSuggestion();
+ }
+
+ m_pAntiImpl->HandleNewUnit( m_nCurrentStartIndex - m_nReplacementBaseIndex, m_nCurrentEndIndex - m_nReplacementBaseIndex );
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnOptionsChanged, void*, EMPTYARG )
+ {
+ //options and dictionaries might have been changed
+ //-> update our internal settings and the dialog
+ implUpdateData();
+
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnIgnore, void*, EMPTYARG )
+ {
+ // simply ignore, and proceed
+ implProceed( sal_False );
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnIgnoreAll, void*, EMPTYARG )
+ {
+ DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnIgnoreAll: no dialog! How this?" );
+
+ if ( m_pConversionDialog )
+ {
+ String sCurrentUnit = m_pConversionDialog->GetCurrentString();
+ DBG_ASSERT( m_sIgnoreList.end() == m_sIgnoreList.find( sCurrentUnit ),
+ "HangulHanjaConversion_Impl, OnIgnoreAll: shouldn't this have been ignored before" );
+
+ // put into the "ignore all" list
+ m_sIgnoreList.insert( sCurrentUnit );
+
+ // and proceed
+ implProceed( sal_False );
+ }
+
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnChange, void*, EMPTYARG )
+ {
+ // change
+ DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
+ if( m_pConversionDialog )
+ implChange( m_pConversionDialog->GetCurrentSuggestion( ) );
+ // and proceed
+ implProceed( sal_False );
+
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnChangeAll, void*, EMPTYARG )
+ {
+ DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnChangeAll: no dialog! How this?" );
+ if ( m_pConversionDialog )
+ {
+ ::rtl::OUString sCurrentUnit( m_pConversionDialog->GetCurrentString() );
+ ::rtl::OUString sChangeInto( m_pConversionDialog->GetCurrentSuggestion( ) );
+
+ if( sChangeInto.getLength() )
+ {
+ // change the current occurence
+ implChange( sChangeInto );
+
+ // put into the "change all" list
+ m_aChangeList.insert( StringMap::value_type( sCurrentUnit, sChangeInto ) );
+ }
+
+ // and proceed
+ implProceed( sal_False );
+ }
+
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnByCharClicked, CheckBox*, _pBox )
+ {
+ m_bByCharacter = _pBox->IsChecked();
+
+ // continue conversion, without advancing to the next unit, but instead continuing with the current unit
+ implProceed( sal_True );
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnConversionTypeChanged, void*, EMPTYARG )
+ {
+ DBG_ASSERT( m_pConversionDialog, "we should always have a dialog here!" );
+ if( m_pConversionDialog )
+ m_eConversionFormat = m_pConversionDialog->GetConversionFormat( );
+ return 0L;
+ }
+
+ //-------------------------------------------------------------------------
+ IMPL_LINK( HangulHanjaConversion_Impl, OnFind, void*, EMPTYARG )
+ {
+ DBG_ASSERT( m_pConversionDialog, "HangulHanjaConversion_Impl::OnFind: where did this come from?" );
+ if ( m_pConversionDialog )
+ {
+ try
+ {
+ ::rtl::OUString sNewOriginal( m_pConversionDialog->GetCurrentSuggestion( ) );
+ Sequence< ::rtl::OUString > aSuggestions;
+
+ DBG_ASSERT( m_xConverter.is(), "HangulHanjaConversion_Impl::OnFind: no converter!" );
+ TextConversionResult aToHanja = m_xConverter->getConversions(
+ sNewOriginal,
+ 0, sNewOriginal.getLength(),
+ m_aSourceLocale,
+ TextConversionType::TO_HANJA,
+ TextConversionOption::NONE
+ );
+ TextConversionResult aToHangul = m_xConverter->getConversions(
+ sNewOriginal,
+ 0, sNewOriginal.getLength(),
+ m_aSourceLocale,
+ TextConversionType::TO_HANGUL,
+ TextConversionOption::NONE
+ );
+
+ bool bHaveToHanja = ( aToHanja.Boundary.startPos < aToHanja.Boundary.endPos );
+ bool bHaveToHangul = ( aToHangul.Boundary.startPos < aToHangul.Boundary.endPos );
+
+ TextConversionResult* pResult = NULL;
+ if ( bHaveToHanja && bHaveToHangul )
+ { // it found convertibles in both directions -> use the first
+ if ( aToHangul.Boundary.startPos < aToHanja.Boundary.startPos )
+ pResult = &aToHangul;
+ else
+ pResult = &aToHanja;
+ }
+ else if ( bHaveToHanja )
+ { // only found toHanja
+ pResult = &aToHanja;
+ }
+ else
+ { // only found toHangul
+ pResult = &aToHangul;
+ }
+ if ( pResult )
+ aSuggestions = pResult->Candidates;
+
+ m_pConversionDialog->SetCurrentString( sNewOriginal, aSuggestions, false );
+ m_pConversionDialog->FocusSuggestion();
+ }
+ catch( const Exception& )
+ {
+ DBG_ERROR( "HangulHanjaConversion_Impl::OnFind: caught an exception!" );
+ }
+ }
+ return 0L;
+ }
+
+ //=========================================================================
+ //= HangulHanjaConversion
+ //=========================================================================
+ //-------------------------------------------------------------------------
+
+ // static member initialization
+ sal_Bool HangulHanjaConversion::m_bUseSavedValues = sal_False;
+ sal_Bool HangulHanjaConversion::m_bTryBothDirectionsSave = sal_False;
+ HHC::ConversionDirection HangulHanjaConversion::m_ePrimaryConversionDirectionSave = HHC::eHangulToHanja;
+
+ //-------------------------------------------------------------------------
+ HangulHanjaConversion::HangulHanjaConversion( Window* _pUIParent,
+ const Reference< XMultiServiceFactory >& _rxORB,
+ const Locale& _rSourceLocale, const Locale& _rTargetLocale,
+ const Font* _pTargetFont,
+ sal_Int32 _nOptions, sal_Bool _bIsInteractive)
+ :m_pImpl( new HangulHanjaConversion_Impl( _pUIParent, _rxORB, _rSourceLocale, _rTargetLocale, _pTargetFont, _nOptions, _bIsInteractive, this ) )
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ HangulHanjaConversion::~HangulHanjaConversion( )
+ {
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion::SetUseSavedConversionDirectionState( sal_Bool bVal )
+ {
+ m_bUseSavedValues = bVal;
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Bool HangulHanjaConversion::IsUseSavedConversionDirectionState()
+ {
+ return m_bUseSavedValues;
+ }
+
+ //-------------------------------------------------------------------------
+ LanguageType HangulHanjaConversion::GetSourceLanguage( ) const
+ {
+ return m_pImpl->GetSourceLang();
+ }
+
+ //-------------------------------------------------------------------------
+ LanguageType HangulHanjaConversion::GetTargetLanguage( ) const
+ {
+ return m_pImpl->GetTargetLang();
+ }
+
+ //-------------------------------------------------------------------------
+ const Font * HangulHanjaConversion::GetTargetFont( ) const
+ {
+ return m_pImpl->GetTargetFont();
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Int32 HangulHanjaConversion::GetConversionOptions( ) const
+ {
+ return m_pImpl->GetConvOptions();
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Bool HangulHanjaConversion::IsInteractive( ) const
+ {
+ return m_pImpl->IsInteractive();
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion::HandleNewUnit( const sal_Int32, const sal_Int32 )
+ {
+ // nothing to do, only derived classes need this.
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion::GetNextPortion( ::rtl::OUString&, LanguageType&, sal_Bool )
+ {
+ DBG_ERROR( "HangulHanjaConversion::GetNextPortion: to be overridden!" );
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion::ReplaceUnit(
+ const sal_Int32, const sal_Int32,
+ const ::rtl::OUString&,
+ const ::rtl::OUString&,
+ const ::com::sun::star::uno::Sequence< sal_Int32 > &,
+ ReplacementAction,
+ LanguageType * )
+ {
+ DBG_ERROR( "HangulHanjaConversion::ReplaceUnit: to be overridden!" );
+ }
+
+ //-------------------------------------------------------------------------
+ sal_Bool HangulHanjaConversion::HasRubySupport() const
+ {
+ DBG_ERROR( "HangulHanjaConversion::HasRubySupport: to be overridden!" );
+ return sal_False;
+ }
+
+ //-------------------------------------------------------------------------
+ void HangulHanjaConversion::ConvertDocument()
+ {
+ if ( m_pImpl->IsValid() )
+ m_pImpl->DoDocumentConversion( );
+ }
+
+//.............................................................................
+} // namespace svx
+//.............................................................................
+
diff --git a/editeng/source/misc/lingu.src b/editeng/source/misc/lingu.src
new file mode 100644
index 0000000000..a3325aedc0
--- /dev/null
+++ b/editeng/source/misc/lingu.src
@@ -0,0 +1,107 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: lingu.src,v $
+ * $Revision: 1.33 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+ // include ---------------------------------------------------------------
+#include <editeng/editrids.hrc>
+ // pragma ----------------------------------------------------------------
+
+ // QueryBoxen ---------------------------------------------------------------
+QueryBox RID_SVXQB_CONTINUE
+{
+ BUTTONS = WB_YES_NO ;
+ DEFBUTTON = WB_DEF_YES ;
+ /* ### ACHTUNG: Neuer Text in Resource? Überprüfung am Anfang des Dokumentes fortsetzen? : šberpr³fung am Anfang des Dokumentes fortsetzen? */
+ /* ### ACHTUNG: Neuer Text in Resource? Überprüfung am Anfang des Dokumentes fortsetzen? : šberpr³fung am Anfang des Dokumentes fortsetzen? */
+ Message [ en-US ] = "Continue checking at beginning of document?" ;
+};
+QueryBox RID_SVXQB_BW_CONTINUE
+{
+ BUTTONS = WB_YES_NO ;
+ DEFBUTTON = WB_DEF_YES ;
+ /* ### ACHTUNG: Neuer Text in Resource? Überprüfung am Ende des Dokumentes fortsetzen? : šberpr³fung am Ende des Dokumentes fortsetzen? */
+ /* ### ACHTUNG: Neuer Text in Resource? Überprüfung am Ende des Dokumentes fortsetzen? : šberpr³fung am Ende des Dokumentes fortsetzen? */
+ Message [ en-US ] = "Continue checking at end of document?" ;
+};
+String RID_SVXSTR_HMERR_THESAURUS
+{
+ /* ### ACHTUNG: Neuer Text in Resource? Ein Thesaurus für die eingestellte Sprache ist nicht verfügbar. \nÜberprüfen Sie bitte Ihre Installation und installieren Sie \ngegebenenfalls die gewünschte Sprache : Ein Thesaurus f³r die eingestellte Sprache ist nicht verf³gbar. \nšberpr³fen Sie bitte Ihre Installation und installieren Sie \ngegebenenfalls die gew³nschte Sprache */
+ /* ### ACHTUNG: Neuer Text in Resource? Ein Thesaurus für die eingestellte Sprache ist nicht verfügbar. \nÜberprüfen Sie bitte Ihre Installation und installieren Sie \ngegebenenfalls die gewünschte Sprache : Ein Thesaurus f³r die eingestellte Sprache ist nicht verf³gbar. \nšberpr³fen Sie bitte Ihre Installation und installieren Sie \ngegebenenfalls die gew³nschte Sprache */
+ Text [ en-US ] = "No thesaurus is available for the selected language. \nPlease check your installation and install the desired language\n" ;
+};
+String RID_SVXSTR_DIC_ERR_UNKNOWN
+{
+ Text [ en-US ] = "Word cannot be added to dictionary\ndue to unknown reason.";
+};
+String RID_SVXSTR_DIC_ERR_FULL
+{
+ Text [ en-US ] = "The dictionary is already full.";
+};
+String RID_SVXSTR_DIC_ERR_READONLY
+{
+ Text [ en-US ] = "The dictionary is read-only.";
+};
+
+ // ********************************************************************** EOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/editeng/source/misc/makefile.mk b/editeng/source/misc/makefile.mk
new file mode 100644
index 0000000000..7eb2d80447
--- /dev/null
+++ b/editeng/source/misc/makefile.mk
@@ -0,0 +1,71 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.18 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org 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 version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..
+
+PRJNAME=editeng
+TARGET=misc
+
+#PROJECTPCH4DLL=TRUE
+#PROJECTPCH=eeng_pch
+#PROJECTPCHSOURCE=eeng_pch
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# --- Allgemein ----------------------------------------------------------
+
+.IF "$(editdebug)" != "" || "$(EDITDEBUG)" != ""
+CDEFS+=-DEDITDEBUG
+.ENDIF
+
+SLOFILES = \
+ $(SLO)$/edtdlg.obj \
+ $(SLO)$/unolingu.obj \
+ $(SLO)$/acorrcfg.obj \
+ $(SLO)$/forbiddencharacterstable.obj \
+ $(SLO)$/hangulhanja.obj \
+ $(SLO)$/splwrap.obj \
+ $(SLO)$/svxacorr.obj \
+ $(SLO)$/SvXMLAutoCorrectExport.obj \
+ $(SLO)$/SvXMLAutoCorrectImport.obj \
+ $(SLO)$/swafopt.obj \
+ $(SLO)$/txtrange.obj
+
+SRS1NAME=misc
+SRC1FILES = \
+ lingu.src
+
+.INCLUDE : target.mk
+
diff --git a/editeng/source/misc/splwrap.cxx b/editeng/source/misc/splwrap.cxx
new file mode 100644
index 0000000000..bf3ae7d092
--- /dev/null
+++ b/editeng/source/misc/splwrap.cxx
@@ -0,0 +1,637 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: splwrap.cxx,v $
+ * $Revision: 1.19 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+#include<rtl/ustring.hxx>
+#include <tools/shl.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/debug.hxx>
+#include <svtools/langtab.hxx>
+
+#ifndef __RSC
+#include <tools/errinf.hxx>
+#endif
+//#include <svxerr.hxx>
+//#include <dlgutil.hxx>
+#include <editeng/unolingu.hxx>
+#include <sfx2/sfxuno.hxx>
+#include <linguistic/lngprops.hxx>
+#include <com/sun/star/frame/XStorable.hpp>
+
+#include <map>
+
+#include <editeng/svxenum.hxx>
+#include <editeng/splwrap.hxx> // Der Wrapper
+#include <editeng/edtdlg.hxx>
+#include <editeng/eerdll.hxx>
+#include <editeng/editrids.hrc>
+#include <editeng/editids.hrc>
+
+#define WAIT_ON() if(pWin != NULL) { pWin->EnterWait(); }
+
+#define WAIT_OFF() if(pWin != NULL) { pWin->LeaveWait(); }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::linguistic2;
+
+
+// misc functions ---------------------------------------------
+
+void SvxPrepareAutoCorrect( String &rOldText, String &rNewText )
+{
+ // This function should be used to strip (or add) trailing '.' from
+ // the strings before passing them on to the autocorrect function in
+ // order that the autocorrect function will hopefully
+ // works properly with normal words and abbreviations (with trailing '.')
+ // independ of if they are at the end of the sentence or not.
+ //
+ // rOldText: text to be replaced
+ // rNewText: replacement text
+
+ xub_StrLen nOldLen = rOldText.Len(),
+ nNewLen = rNewText.Len();
+ if (nOldLen && nNewLen)
+ {
+ sal_Bool bOldHasDot = sal_Unicode( '.' ) == rOldText.GetChar( nOldLen - 1 ),
+ bNewHasDot = sal_Unicode( '.' ) == rNewText.GetChar( nNewLen - 1 );
+ if (bOldHasDot && !bNewHasDot
+ /*this is: !(bOldHasDot && bNewHasDot) && bOldHasDot*/)
+ rOldText.Erase( nOldLen - 1 );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+#define SVX_LANG_NEED_CHECK 0
+#define SVX_LANG_OK 1
+#define SVX_LANG_MISSING 2
+#define SVX_LANG_MISSING_DO_WARN 3
+
+#define SVX_FLAGS_NEW
+
+
+struct lt_LanguageType
+{
+ bool operator()( LanguageType n1, LanguageType n2 ) const
+ {
+ return n1 < n2;
+ }
+};
+
+typedef std::map< LanguageType, USHORT, lt_LanguageType > LangCheckState_map_t;
+
+static LangCheckState_map_t & GetLangCheckState()
+{
+ static LangCheckState_map_t aLangCheckState;
+ return aLangCheckState;
+}
+
+void SvxSpellWrapper::ShowLanguageErrors()
+{
+ // display message boxes for languages not available for
+ // spellchecking or hyphenation
+ LangCheckState_map_t &rLCS = GetLangCheckState();
+ LangCheckState_map_t::iterator aIt( rLCS.begin() );
+ while (aIt != rLCS.end())
+ {
+ LanguageType nLang = aIt->first;
+ sal_uInt16 nVal = aIt->second;
+ sal_uInt16 nTmpSpell = nVal & 0x00FF;
+ sal_uInt16 nTmpHyph = (nVal >> 8) & 0x00FF;
+
+ if (SVX_LANG_MISSING_DO_WARN == nTmpSpell)
+ {
+ String aErr( SvtLanguageTable::GetLanguageString( nLang ) );
+ ErrorHandler::HandleError(
+ *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
+ nTmpSpell = SVX_LANG_MISSING;
+ }
+ if (SVX_LANG_MISSING_DO_WARN == nTmpHyph)
+ {
+ String aErr( SvtLanguageTable::GetLanguageString( nLang ) );
+ ErrorHandler::HandleError(
+ *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
+ nTmpHyph = SVX_LANG_MISSING;
+ }
+
+ rLCS[ nLang ] = (nTmpHyph << 8) | nTmpSpell;
+ ++aIt;
+ }
+
+}
+
+SvxSpellWrapper::~SvxSpellWrapper()
+{
+}
+
+/*--------------------------------------------------------------------
+ * Beschreibung: Ctor, die Pruefreihenfolge wird festgelegt
+ *
+ * !bStart && !bOtherCntnt: BODY_END, BODY_START, OTHER
+ * !bStart && bOtherCntnt: OTHER, BODY
+ * bStart && !bOtherCntnt: BODY_END, OTHER
+ * bStart && bOtherCntnt: OTHER
+ *
+ --------------------------------------------------------------------*/
+
+SvxSpellWrapper::SvxSpellWrapper( Window* pWn,
+ Reference< XSpellChecker1 > &xSpellChecker,
+ const sal_Bool bStart, const sal_Bool bIsAllRight,
+ const sal_Bool bOther, const sal_Bool bRevAllow ) :
+
+ pWin ( pWn ),
+ xSpell ( xSpellChecker ),
+ bOtherCntnt ( bOther ),
+ bDialog ( sal_False ),
+ bHyphen ( sal_False ),
+ bAuto ( sal_False ),
+ bStartChk ( bOther ),
+ bRevAllowed ( bRevAllow ),
+ bAllRight ( bIsAllRight )
+{
+ Reference< beans::XPropertySet > xProp( SvxGetLinguPropertySet() );
+ sal_Bool bWrapReverse = xProp.is() ?
+ *(sal_Bool*)xProp->getPropertyValue(
+ ::rtl::OUString::createFromAscii(UPN_IS_WRAP_REVERSE) ).getValue()
+ : sal_False;
+ bReverse = bRevAllow && bWrapReverse;
+ bStartDone = bOther || ( !bReverse && bStart );
+ bEndDone = bReverse && bStart && !bOther;
+}
+
+// -----------------------------------------------------------------------
+
+SvxSpellWrapper::SvxSpellWrapper( Window* pWn,
+ Reference< XHyphenator > &xHyphenator,
+ const sal_Bool bStart, const sal_Bool bOther ) :
+ pWin ( pWn ),
+ xHyph ( xHyphenator ),
+ bOtherCntnt ( bOther ),
+ bDialog ( sal_False ),
+ bHyphen ( sal_False ),
+ bAuto ( sal_False ),
+ bReverse ( sal_False ),
+ bStartDone ( bOther || ( !bReverse && bStart ) ),
+ bEndDone ( bReverse && bStart && !bOther ),
+ bStartChk ( bOther ),
+ bRevAllowed ( sal_False ),
+ bAllRight ( sal_True )
+{
+}
+
+// -----------------------------------------------------------------------
+
+sal_Int16 SvxSpellWrapper::CheckSpellLang(
+ Reference< XSpellChecker1 > xSpell, sal_Int16 nLang)
+{
+ LangCheckState_map_t &rLCS = GetLangCheckState();
+
+ LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
+ sal_uInt16 nVal = aIt == rLCS.end() ? SVX_LANG_NEED_CHECK : aIt->second;
+
+ if (aIt == rLCS.end())
+ rLCS[ nLang ] = nVal;
+
+ if (SVX_LANG_NEED_CHECK == (nVal & 0x00FF))
+ {
+ sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
+ if (xSpell.is() && xSpell->hasLanguage( nLang ))
+ nTmpVal = SVX_LANG_OK;
+ nVal &= 0xFF00;
+ nVal |= nTmpVal;
+
+ rLCS[ nLang ] = nVal;
+ }
+
+ return (sal_Int16) nVal;
+}
+
+sal_Int16 SvxSpellWrapper::CheckHyphLang(
+ Reference< XHyphenator > xHyph, sal_Int16 nLang)
+{
+ LangCheckState_map_t &rLCS = GetLangCheckState();
+
+ LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
+ sal_uInt16 nVal = aIt == rLCS.end() ? 0 : aIt->second;
+
+ if (aIt == rLCS.end())
+ rLCS[ nLang ] = nVal;
+
+ if (SVX_LANG_NEED_CHECK == ((nVal >> 8) & 0x00FF))
+ {
+ sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
+ if (xHyph.is() && xHyph->hasLocale( SvxCreateLocale( nLang ) ))
+ nTmpVal = SVX_LANG_OK;
+ nVal &= 0x00FF;
+ nVal |= nTmpVal << 8;
+
+ rLCS[ nLang ] = nVal;
+ }
+
+ return (sal_Int16) nVal;
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::SpellStart( SvxSpellArea /*eSpell*/ )
+{ // Hier muessen die notwendigen Vorbereitungen fuer SpellContinue
+} // im uebergebenen Bereich getroffen werden.
+
+// -----------------------------------------------------------------------
+
+
+sal_Bool SvxSpellWrapper::HasOtherCnt()
+{
+ return sal_False; // Gibt es ueberhaupt einen Sonderbereich?
+}
+
+// -----------------------------------------------------------------------
+
+
+sal_Bool SvxSpellWrapper::SpellMore()
+{
+ return sal_False; // Sollen weitere Dokumente geprueft werden?
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::SpellEnd()
+{ // Bereich ist abgeschlossen, ggf. Aufraeumen
+
+ // display error for last language not found
+ ShowLanguageErrors();
+}
+
+// -----------------------------------------------------------------------
+
+
+sal_Bool SvxSpellWrapper::SpellContinue()
+{
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+void SvxSpellWrapper::AutoCorrect( const String&, const String& )
+{
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::ScrollArea()
+{ // Scrollarea einstellen
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::ChangeWord( const String&, const sal_uInt16 )
+{ // Wort ersetzen
+}
+
+// -----------------------------------------------------------------------
+
+
+String SvxSpellWrapper::GetThesWord()
+{
+ // Welches Wort soll nachgeschlagen werden?
+ return String();
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::ChangeThesWord( const String& )
+{
+ // Wort wg. Thesaurus ersetzen
+}
+
+// -----------------------------------------------------------------------
+
+void SvxSpellWrapper::StartThesaurus( const String &rWord, sal_uInt16 nLanguage )
+{
+ Reference< XThesaurus > xThes( SvxGetThesaurus() );
+ if (!xThes.is())
+ {
+ InfoBox( pWin, EE_RESSTR( RID_SVXSTR_HMERR_THESAURUS ) ).Execute();
+ return;
+ }
+
+ WAIT_ON(); // while looking up for initial word
+ EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
+ AbstractThesaurusDialog* pDlg = pFact->CreateThesaurusDialog( pWin, xThes, rWord, nLanguage );
+ WAIT_OFF();
+ if ( pDlg->Execute()== RET_OK )
+ {
+ ChangeThesWord( pDlg->GetWord() );
+ }
+ delete pDlg;
+}
+
+// -----------------------------------------------------------------------
+
+void SvxSpellWrapper::ReplaceAll( const String &, sal_Int16 )
+{ // Wort aus der Replace-Liste ersetzen
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::SetLanguage( const sal_uInt16 )
+{ // Sprache aendern
+}
+
+// -----------------------------------------------------------------------
+
+
+void SvxSpellWrapper::InsertHyphen( const sal_uInt16 )
+{ // Hyphen einfuegen bzw. loeschen
+}
+
+// -----------------------------------------------------------------------
+// Pruefung der Dokumentbereiche in der durch die Flags angegebenen Reihenfolge
+
+
+void SvxSpellWrapper::SpellDocument( )
+{
+ if ( bOtherCntnt )
+ {
+ bReverse = sal_False;
+ SpellStart( SVX_SPELL_OTHER );
+ }
+ else
+ {
+ bStartChk = bReverse;
+ SpellStart( bReverse ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
+ }
+
+ if ( FindSpellError() )
+ {
+ Reference< XSpellAlternatives > xAlt( GetLast(), UNO_QUERY );
+ Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
+
+ Window *pOld = pWin;
+ bDialog = sal_True;
+ if (xHyphWord.is())
+ {
+ EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create();
+ AbstractHyphenWordDialog* pDlg = pFact->CreateHyphenWordDialog( pWin,
+ xHyphWord->getWord(),
+ SvxLocaleToLanguage( xHyphWord->getLocale() ),
+ xHyph, this );
+ pWin = pDlg->GetWindow();
+ pDlg->Execute();
+ delete pDlg;
+ }
+ bDialog = sal_False;
+ pWin = pOld;
+ };
+}
+
+// -----------------------------------------------------------------------
+// Naechsten Bereich auswaehlen
+
+
+sal_Bool SvxSpellWrapper::SpellNext( )
+{
+ Reference< beans::XPropertySet > xProp( SvxGetLinguPropertySet() );
+ sal_Bool bWrapReverse = xProp.is() ?
+ *(sal_Bool*)xProp->getPropertyValue(
+ ::rtl::OUString::createFromAscii(UPN_IS_WRAP_REVERSE) ).getValue()
+ : sal_False;
+ sal_Bool bActRev = bRevAllowed && bWrapReverse;
+
+ // bActRev ist die Richtung nach dem Spellen, bReverse die am Anfang.
+ if( bActRev == bReverse )
+ { // Keine Richtungsaenderung, also ist
+ if( bStartChk ) // der gewuenschte Bereich ( bStartChk )
+ bStartDone = sal_True; // vollstaendig abgearbeitet.
+ else
+ bEndDone = sal_True;
+ }
+ else if( bReverse == bStartChk ) // Bei einer Richtungsaenderung kann
+ { // u.U. auch ein Bereich abgearbeitet sein.
+ if( bStartChk ) // Sollte der vordere Teil rueckwaerts gespellt
+ bEndDone = sal_True; // werden und wir kehren unterwegs um, so ist
+ else // der hintere Teil abgearbeitet (und umgekehrt).
+ bStartDone = sal_True;
+ }
+
+ bReverse = bActRev;
+ if( bOtherCntnt && bStartDone && bEndDone ) // Dokument komplett geprueft?
+ {
+ if ( SpellMore() ) // ein weiteres Dokument pruefen?
+ {
+ bOtherCntnt = sal_False;
+ bStartDone = !bReverse;
+ bEndDone = bReverse;
+ SpellStart( SVX_SPELL_BODY );
+ return sal_True;
+ }
+ return sal_False;
+ }
+
+ sal_Bool bGoOn = sal_False;
+
+ if ( bOtherCntnt )
+ {
+ bStartChk = sal_False;
+ SpellStart( SVX_SPELL_BODY );
+ bGoOn = sal_True;
+ }
+ else if ( bStartDone && bEndDone )
+ {
+ sal_Bool bIsSpellSpecial = xProp.is() ?
+ *(sal_Bool*)xProp->getPropertyValue(
+ ::rtl::OUString::createFromAscii(UPN_IS_SPELL_SPECIAL) ).getValue()
+ : sal_False;
+ // Bodybereich erledigt, Frage nach Sonderbereich
+ if( !IsHyphen() && bIsSpellSpecial && HasOtherCnt() )
+ {
+ SpellStart( SVX_SPELL_OTHER );
+ bOtherCntnt = bGoOn = sal_True;
+ }
+ else if ( SpellMore() ) // ein weiteres Dokument pruefen?
+ {
+ bOtherCntnt = sal_False;
+ bStartDone = !bReverse;
+ bEndDone = bReverse;
+ SpellStart( SVX_SPELL_BODY );
+ return sal_True;
+ }
+ }
+ else
+ {
+ // Ein BODY_Bereich erledigt, Frage nach dem anderen BODY_Bereich
+ WAIT_OFF();
+
+// Sobald im Dialog das DontWrapAround gesetzt werden kann, kann der
+// folgende #ifdef-Zweig aktiviert werden ...
+#ifdef USED
+ sal_Bool bDontWrapAround = IsHyphen() ?
+ pSpell->GetOptions() & DONT_WRAPAROUND :
+ pSpell->GetHyphOptions() & HYPH_DONT_WRAPAROUND;
+ if( bDontWrapAround )
+#else
+ sal_uInt16 nResId = bReverse ? RID_SVXQB_BW_CONTINUE : RID_SVXQB_CONTINUE;
+ QueryBox aBox( pWin, EditResId( nResId ) );
+ if ( aBox.Execute() != RET_YES )
+#endif
+
+ {
+ // Verzicht auf den anderen Bereich, ggf. Frage nach Sonderbereich
+ WAIT_ON();
+ bStartDone = bEndDone = sal_True;
+ return SpellNext();
+ }
+ else
+ {
+ bStartChk = !bStartDone;
+ SpellStart( bStartChk ? SVX_SPELL_BODY_START : SVX_SPELL_BODY_END );
+ bGoOn = sal_True;
+ }
+ WAIT_ON();
+ }
+ return bGoOn;
+}
+
+// -----------------------------------------------------------------------
+
+Reference< XDictionary > SvxSpellWrapper::GetAllRightDic() const
+{
+ Reference< XDictionary > xDic;
+
+ Reference< XDictionaryList > xDicList( SvxGetDictionaryList() );
+ if (xDicList.is())
+ {
+ Sequence< Reference< XDictionary > > aDics( xDicList->getDictionaries() );
+ const Reference< XDictionary > *pDic = aDics.getConstArray();
+ sal_Int32 nCount = aDics.getLength();
+
+ sal_Int32 i = 0;
+ while (!xDic.is() && i < nCount)
+ {
+ Reference< XDictionary > xTmp( pDic[i], UNO_QUERY );
+ if (xTmp.is())
+ {
+ if ( xTmp->isActive() &&
+ xTmp->getDictionaryType() != DictionaryType_NEGATIVE &&
+ SvxLocaleToLanguage( xTmp->getLocale() ) == LANGUAGE_NONE )
+ {
+ Reference< frame::XStorable > xStor( xTmp, UNO_QUERY );
+ if (xStor.is() && xStor->hasLocation() && !xStor->isReadonly())
+ {
+ xDic = xTmp;
+ }
+ }
+ }
+ ++i;
+ }
+
+ if (!xDic.is())
+ {
+ xDic = SvxGetOrCreatePosDic( xDicList );
+ if (xDic.is())
+ xDic->setActive( sal_True );
+ }
+ }
+
+ return xDic;
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvxSpellWrapper::FindSpellError()
+{
+ ShowLanguageErrors();
+
+ Reference< XInterface > xRef;
+
+ WAIT_ON();
+ sal_Bool bSpell = sal_True;
+
+ Reference< XDictionary > xAllRightDic;
+ if (IsAllRight())
+ xAllRightDic = GetAllRightDic();
+
+ while ( bSpell )
+ {
+ SpellContinue();
+
+ Reference< XSpellAlternatives > xAlt( GetLast(), UNO_QUERY );
+ Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
+
+ if (xAlt.is())
+ {
+ if (IsAllRight() && xAllRightDic.is())
+ {
+ xAllRightDic->add( xAlt->getWord(), sal_False, ::rtl::OUString() );
+ }
+ else
+ {
+ // look up in ChangeAllList for misspelled word
+ Reference< XDictionary > xChangeAllList(
+ SvxGetChangeAllList(), UNO_QUERY );
+ Reference< XDictionaryEntry > xEntry;
+ if (xChangeAllList.is())
+ xEntry = xChangeAllList->getEntry( xAlt->getWord() );
+
+ if (xEntry.is())
+ {
+ // replace word without asking
+ ReplaceAll( xEntry->getReplacementText(),
+ SvxLocaleToLanguage( xAlt->getLocale() ) );
+ }
+ else
+ bSpell = sal_False;
+ }
+ }
+ else if (xHyphWord.is())
+ bSpell = sal_False;
+ else
+ {
+ SpellEnd();
+ bSpell = SpellNext();
+ }
+ }
+ WAIT_OFF();
+ return GetLast().is();
+}
+
+
+
diff --git a/editeng/source/misc/svxacorr.cxx b/editeng/source/misc/svxacorr.cxx
new file mode 100644
index 0000000000..3a3751b2c3
--- /dev/null
+++ b/editeng/source/misc/svxacorr.cxx
@@ -0,0 +1,2706 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: svxacorr.cxx,v $
+ * $Revision: 1.62 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+
+#include <com/sun/star/io/XStream.hpp>
+#include <tools/urlobj.hxx>
+#include <tools/table.hxx>
+#include <i18npool/mslangid.hxx>
+#include <vcl/svapp.hxx>
+#include <sot/storinfo.hxx>
+// fuer die Sort-String-Arrays aus dem SVMEM.HXX
+#define _SVSTDARR_STRINGSISORTDTOR
+#define _SVSTDARR_STRINGSDTOR
+#include <svl/svstdarr.hxx>
+#include <svl/fstathelper.hxx>
+#include <svtools/helpopt.hxx>
+#include <svl/urihelper.hxx>
+#include <unotools/charclass.hxx>
+#include <com/sun/star/i18n/UnicodeType.hdl>
+#include <unotools/collatorwrapper.hxx>
+#include <com/sun/star/i18n/CollatorOptions.hpp>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/transliterationwrapper.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <editeng/editids.hrc>
+#include <sot/storage.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/svxacorr.hxx>
+#include <editeng/unolingu.hxx>
+#include <helpid.hrc>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/XParser.hpp>
+#include <unotools/streamwrap.hxx>
+#include <SvXMLAutoCorrectImport.hxx>
+#include <SvXMLAutoCorrectExport.hxx>
+#include <ucbhelper/content.hxx>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <xmloff/xmltoken.hxx>
+#include <vcl/help.hxx>
+
+using namespace ::com::sun::star::ucb;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+using namespace ::rtl;
+using namespace ::utl;
+
+const int C_NONE = 0x00;
+const int C_FULL_STOP = 0x01;
+const int C_EXCLAMATION_MARK = 0x02;
+const int C_QUESTION_MARK = 0x04;
+
+static const sal_Char pImplWrdStt_ExcptLstStr[] = "WordExceptList";
+static const sal_Char pImplCplStt_ExcptLstStr[] = "SentenceExceptList";
+static const sal_Char pImplAutocorr_ListStr[] = "DocumentList";
+static const sal_Char pXMLImplWrdStt_ExcptLstStr[] = "WordExceptList.xml";
+static const sal_Char pXMLImplCplStt_ExcptLstStr[] = "SentenceExceptList.xml";
+static const sal_Char pXMLImplAutocorr_ListStr[] = "DocumentList.xml";
+
+static const sal_Char
+ /* auch bei diesen Anfaengen - Klammern auf und alle Arten von Anf.Zei. */
+ sImplSttSkipChars[] = "\"\'([{\x83\x84\x89\x91\x92\x93\x94",
+ /* auch bei diesen Ende - Klammern auf und alle Arten von Anf.Zei. */
+ sImplEndSkipChars[] = "\"\')]}\x83\x84\x89\x91\x92\x93\x94";
+
+// diese Zeichen sind in Worten erlaubt: (fuer FnCptlSttSntnc)
+static const sal_Char sImplWordChars[] = "-'";
+
+void EncryptBlockName_Imp( String& rName );
+void DecryptBlockName_Imp( String& rName );
+
+
+// FileVersions Nummern fuer die Ersetzungs-/Ausnahmelisten getrennt
+#define WORDLIST_VERSION_358 1
+#define EXEPTLIST_VERSION_358 0
+
+
+_SV_IMPL_SORTAR_ALG( SvxAutocorrWordList, SvxAutocorrWordPtr )
+TYPEINIT0(SvxAutoCorrect)
+
+typedef SvxAutoCorrectLanguageLists* SvxAutoCorrectLanguageListsPtr;
+DECLARE_TABLE( SvxAutoCorrLanguageTable_Impl, SvxAutoCorrectLanguageListsPtr)
+
+DECLARE_TABLE( SvxAutoCorrLastFileAskTable_Impl, long )
+
+
+inline int IsWordDelim( const sal_Unicode c )
+{
+ return ' ' == c || '\t' == c || 0x0a == c ||
+ 0xA0 == c || 0x2011 == c || 0x1 == c;
+}
+
+inline int IsLowerLetter( sal_Int32 nCharType )
+{
+ return CharClass::isLetterType( nCharType ) &&
+ 0 == ( ::com::sun::star::i18n::KCharacterType::UPPER & nCharType);
+}
+inline int IsUpperLetter( sal_Int32 nCharType )
+{
+ return CharClass::isLetterType( nCharType ) &&
+ 0 == ( ::com::sun::star::i18n::KCharacterType::LOWER & nCharType);
+}
+
+BOOL lcl_IsSymbolChar( CharClass& rCC, const String& rTxt,
+ xub_StrLen nStt, xub_StrLen nEnd )
+{
+ for( ; nStt < nEnd; ++nStt )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ sal_Int32 nCharType;
+ sal_Int32 nChType;
+ nCharType = rCC.getCharacterType( rTxt, nStt );
+ nChType = rCC.getType( rTxt, nStt );
+#endif
+ if( ::com::sun::star::i18n::UnicodeType::PRIVATE_USE ==
+ rCC.getType( rTxt, nStt ))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static BOOL lcl_IsInAsciiArr( const sal_Char* pArr, const sal_Unicode c )
+{
+ BOOL bRet = FALSE;
+ for( ; *pArr; ++pArr )
+ if( *pArr == c )
+ {
+ bRet = TRUE;
+ break;
+ }
+ return bRet;
+}
+
+SvxAutoCorrDoc::~SvxAutoCorrDoc()
+{
+}
+
+
+ // wird nach dem austauschen der Zeichen von den Funktionen
+ // - FnCptlSttWrd
+ // - FnCptlSttSntnc
+ // gerufen. Dann koennen die Worte ggfs. in die Ausnahmelisten
+ // aufgenommen werden.
+void SvxAutoCorrDoc::SaveCpltSttWord( ULONG, xub_StrLen, const String&,
+ sal_Unicode )
+{
+}
+
+LanguageType SvxAutoCorrDoc::GetLanguage( xub_StrLen , BOOL ) const
+{
+ return LANGUAGE_SYSTEM;
+}
+
+static ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory >& GetProcessFact()
+{
+ static ::com::sun::star::uno::Reference<
+ ::com::sun::star::lang::XMultiServiceFactory > xMSF =
+ ::comphelper::getProcessServiceFactory();
+ return xMSF;
+}
+
+static USHORT GetAppLang()
+{
+ return Application::GetSettings().GetLanguage();
+}
+static LocaleDataWrapper& GetLocaleDataWrapper( USHORT nLang )
+{
+ static LocaleDataWrapper aLclDtWrp( GetProcessFact(),
+ SvxCreateLocale( GetAppLang() ) );
+ ::com::sun::star::lang::Locale aLcl( SvxCreateLocale( nLang ));
+ const ::com::sun::star::lang::Locale& rLcl = aLclDtWrp.getLoadedLocale();
+ if( aLcl.Language != rLcl.Language ||
+ aLcl.Country != rLcl.Country ||
+ aLcl.Variant != rLcl.Variant )
+ aLclDtWrp.setLocale( aLcl );
+ return aLclDtWrp;
+}
+static TransliterationWrapper& GetIgnoreTranslWrapper()
+{
+ static int bIsInit = 0;
+ static TransliterationWrapper aWrp( GetProcessFact(),
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_CASE |
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA |
+ ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
+ if( !bIsInit )
+ {
+ aWrp.loadModuleIfNeeded( GetAppLang() );
+ bIsInit = 1;
+ }
+ return aWrp;
+}
+static CollatorWrapper& GetCollatorWrapper()
+{
+ static int bIsInit = 0;
+ static CollatorWrapper aCollWrp( GetProcessFact() );
+ if( !bIsInit )
+ {
+ aCollWrp.loadDefaultCollator( SvxCreateLocale( GetAppLang() ), 0 );
+ bIsInit = 1;
+ }
+ return aCollWrp;
+}
+
+
+void SvxAutocorrWordList::DeleteAndDestroy( USHORT nP, USHORT nL )
+{
+ if( nL )
+ {
+ DBG_ASSERT( nP < nA && nP + nL <= nA, "ERR_VAR_DEL" );
+ for( USHORT n=nP; n < nP + nL; n++ )
+ delete *((SvxAutocorrWordPtr*)pData+n);
+ SvPtrarr::Remove( nP, nL );
+ }
+}
+
+
+BOOL SvxAutocorrWordList::Seek_Entry( const SvxAutocorrWordPtr aE, USHORT* pP ) const
+{
+ register USHORT nO = SvxAutocorrWordList_SAR::Count(),
+ nM,
+ nU = 0;
+ if( nO > 0 )
+ {
+ CollatorWrapper& rCmp = ::GetCollatorWrapper();
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ long nCmp = rCmp.compareString( aE->GetShort(),
+ (*((SvxAutocorrWordPtr*)pData + nM))->GetShort() );
+ if( 0 == nCmp )
+ {
+ if( pP ) *pP = nM;
+ return TRUE;
+ }
+ else if( 0 < nCmp )
+ nU = nM + 1;
+ else if( nM == 0 )
+ {
+ if( pP ) *pP = nU;
+ return FALSE;
+ }
+ else
+ nO = nM - 1;
+ }
+ }
+ if( pP ) *pP = nU;
+ return FALSE;
+}
+
+/* -----------------18.11.98 15:28-------------------
+ *
+ * --------------------------------------------------*/
+void lcl_ClearTable(SvxAutoCorrLanguageTable_Impl& rLangTable)
+{
+ SvxAutoCorrectLanguageListsPtr pLists = rLangTable.Last();
+ while(pLists)
+ {
+ delete pLists;
+ pLists = rLangTable.Prev();
+ }
+ rLangTable.Clear();
+}
+
+/* -----------------03.11.06 10:15-------------------
+ *
+ * --------------------------------------------------*/
+
+sal_Bool SvxAutoCorrect::IsAutoCorrectChar( sal_Unicode cChar )
+{
+ return cChar == '\0' || cChar == '\t' || cChar == 0x0a ||
+ cChar == ' ' || cChar == '\'' || cChar == '\"' ||
+ cChar == '*' || cChar == '_' ||
+ cChar == '.' || cChar == ',' || cChar == ';' ||
+ cChar == ':' || cChar == '?' || cChar == '!';
+}
+
+/* -----------------19.11.98 10:15-------------------
+ *
+ * --------------------------------------------------*/
+long SvxAutoCorrect::GetDefaultFlags()
+{
+ long nRet = Autocorrect
+ | CptlSttSntnc
+ | CptlSttWrd
+ | ChgFractionSymbol
+ | ChgOrdinalNumber
+ | ChgToEnEmDash
+ | ChgWeightUnderl
+ | SetINetAttr
+ | ChgQuotes
+ | SaveWordCplSttLst
+ | SaveWordWrdSttLst;
+ LanguageType eLang = GetAppLang();
+ switch( eLang )
+ {
+ case LANGUAGE_ENGLISH:
+ case LANGUAGE_ENGLISH_US:
+ case LANGUAGE_ENGLISH_UK:
+ case LANGUAGE_ENGLISH_AUS:
+ case LANGUAGE_ENGLISH_CAN:
+ case LANGUAGE_ENGLISH_NZ:
+ case LANGUAGE_ENGLISH_EIRE:
+ case LANGUAGE_ENGLISH_SAFRICA:
+ case LANGUAGE_ENGLISH_JAMAICA:
+ case LANGUAGE_ENGLISH_CARRIBEAN:
+ nRet &= ~(ChgQuotes|ChgSglQuotes);
+ break;
+ }
+ return nRet;
+}
+
+
+SvxAutoCorrect::SvxAutoCorrect( const String& rShareAutocorrFile,
+ const String& rUserAutocorrFile )
+ : sShareAutoCorrFile( rShareAutocorrFile ),
+ sUserAutoCorrFile( rUserAutocorrFile ),
+ pLangTable( new SvxAutoCorrLanguageTable_Impl ),
+ pLastFileTable( new SvxAutoCorrLastFileAskTable_Impl ),
+ pCharClass( 0 ),
+ cStartDQuote( 0 ), cEndDQuote( 0 ), cStartSQuote( 0 ), cEndSQuote( 0 )
+{
+ nFlags = SvxAutoCorrect::GetDefaultFlags();
+
+ c1Div2 = ByteString::ConvertToUnicode( '\xBD', RTL_TEXTENCODING_MS_1252 );
+ c1Div4 = ByteString::ConvertToUnicode( '\xBC', RTL_TEXTENCODING_MS_1252 );
+ c3Div4 = ByteString::ConvertToUnicode( '\xBE', RTL_TEXTENCODING_MS_1252 );
+ cEmDash = ByteString::ConvertToUnicode( '\x97', RTL_TEXTENCODING_MS_1252 );
+ cEnDash = ByteString::ConvertToUnicode( '\x96', RTL_TEXTENCODING_MS_1252 );
+}
+
+SvxAutoCorrect::SvxAutoCorrect( const SvxAutoCorrect& rCpy )
+: sShareAutoCorrFile( rCpy.sShareAutoCorrFile ),
+ sUserAutoCorrFile( rCpy.sUserAutoCorrFile ),
+
+ aSwFlags( rCpy.aSwFlags ),
+
+ pLangTable( new SvxAutoCorrLanguageTable_Impl ),
+ pLastFileTable( new SvxAutoCorrLastFileAskTable_Impl ),
+ pCharClass( 0 ),
+
+ nFlags( rCpy.nFlags & ~(ChgWordLstLoad|CplSttLstLoad|WrdSttLstLoad)),
+ cStartDQuote( rCpy.cStartDQuote ), cEndDQuote( rCpy.cEndDQuote ),
+ cStartSQuote( rCpy.cStartSQuote ), cEndSQuote( rCpy.cEndSQuote ),
+ c1Div2( rCpy.c1Div2 ), c1Div4( rCpy.c1Div4 ), c3Div4( rCpy.c3Div4 ),
+ cEmDash( rCpy.cEmDash ), cEnDash( rCpy.cEnDash )
+{
+}
+
+
+SvxAutoCorrect::~SvxAutoCorrect()
+{
+ lcl_ClearTable(*pLangTable);
+ delete pLangTable;
+ delete pLastFileTable;
+ delete pCharClass;
+}
+
+void SvxAutoCorrect::_GetCharClass( LanguageType eLang )
+{
+ delete pCharClass;
+ pCharClass = new CharClass( SvxCreateLocale( eLang ));
+ eCharClassLang = eLang;
+}
+
+void SvxAutoCorrect::SetAutoCorrFlag( long nFlag, BOOL bOn )
+{
+ long nOld = nFlags;
+ nFlags = bOn ? nFlags | nFlag
+ : nFlags & ~nFlag;
+
+ if( !bOn )
+ {
+ if( (nOld & CptlSttSntnc) != (nFlags & CptlSttSntnc) )
+ nFlags &= ~CplSttLstLoad;
+ if( (nOld & CptlSttWrd) != (nFlags & CptlSttWrd) )
+ nFlags &= ~WrdSttLstLoad;
+ if( (nOld & Autocorrect) != (nFlags & Autocorrect) )
+ nFlags &= ~ChgWordLstLoad;
+ }
+}
+
+
+ // Zwei Grossbuchstaben am Wort-Anfang ??
+BOOL SvxAutoCorrect::FnCptlSttWrd( SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nSttPos, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+ BOOL bRet = FALSE;
+ CharClass& rCC = GetCharClass( eLang );
+
+ // loesche alle nicht alpanum. Zeichen am Wortanfang/-ende und
+ // teste dann ( erkennt: "(min.", "/min.", usw.)
+ for( ; nSttPos < nEndPos; ++nSttPos )
+ if( rCC.isLetterNumeric( rTxt, nSttPos ))
+ break;
+ for( ; nSttPos < nEndPos; --nEndPos )
+ if( rCC.isLetterNumeric( rTxt, nEndPos - 1 ))
+ break;
+
+ // Zwei Grossbuchstaben am Wort-Anfang ??
+ if( nSttPos+2 < nEndPos &&
+ IsUpperLetter( rCC.getCharacterType( rTxt, nSttPos )) &&
+ IsUpperLetter( rCC.getCharacterType( rTxt, ++nSttPos )) &&
+ // ist das 3. Zeichen ein klein geschiebenes Alpha-Zeichen
+ IsLowerLetter( rCC.getCharacterType( rTxt, nSttPos +1 )) &&
+ // keine Sonder-Attribute ersetzen
+ 0x1 != rTxt.GetChar( nSttPos ) && 0x2 != rTxt.GetChar( nSttPos ))
+ {
+ // teste ob das Wort in einer Ausnahmeliste steht
+ String sWord( rTxt.Copy( nSttPos - 1, nEndPos - nSttPos + 1 ));
+ if( !FindInWrdSttExceptList(eLang, sWord) )
+ {
+ sal_Unicode cSave = rTxt.GetChar( nSttPos );
+ String sChar( cSave );
+ rCC.toLower( sChar );
+ if( sChar.GetChar(0) != cSave && rDoc.Replace( nSttPos, sChar ))
+ {
+ if( SaveWordWrdSttLst & nFlags )
+ rDoc.SaveCpltSttWord( CptlSttWrd, nSttPos, sWord, cSave );
+ bRet = TRUE;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SvxAutoCorrect::FnChgFractionSymbol(
+ SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nSttPos, xub_StrLen nEndPos )
+{
+ sal_Unicode cChar = 0;
+
+ for( ; nSttPos < nEndPos; ++nSttPos )
+ if( !lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nSttPos ) ))
+ break;
+ for( ; nSttPos < nEndPos; --nEndPos )
+ if( !lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nEndPos - 1 ) ))
+ break;
+
+ // 1/2, 1/4, ... ersetzen durch das entsprechende Zeichen vom Font
+ if( 3 == nEndPos - nSttPos && '/' == rTxt.GetChar( nSttPos+1 ))
+ {
+ switch( ( rTxt.GetChar( nSttPos )) * 256 + rTxt.GetChar( nEndPos-1 ))
+ {
+ case '1' * 256 + '2': cChar = c1Div2; break;
+ case '1' * 256 + '4': cChar = c1Div4; break;
+ case '3' * 256 + '4': cChar = c3Div4; break;
+ }
+
+ if( cChar )
+ {
+ // also austauschen:
+ rDoc.Delete( nSttPos+1, nEndPos );
+ rDoc.Replace( nSttPos, cChar );
+ }
+ }
+ return 0 != cChar;
+}
+
+
+BOOL SvxAutoCorrect::FnChgOrdinalNumber(
+ SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nSttPos, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+// 1st, 2nd, 3rd, 4 - 0th
+// 201th oder 201st
+// 12th oder 12nd
+ CharClass& rCC = GetCharClass( eLang );
+ BOOL bChg = FALSE;
+
+ for( ; nSttPos < nEndPos; ++nSttPos )
+ if( !lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nSttPos ) ))
+ break;
+ for( ; nSttPos < nEndPos; --nEndPos )
+ if( !lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nEndPos - 1 ) ))
+ break;
+
+ if( 2 < nEndPos - nSttPos &&
+ rCC.isDigit( rTxt, nEndPos - 3 ) )
+ {
+ static sal_Char __READONLY_DATA
+ sAll[] = "th", /* rest */
+ sFirst[] = "st", /* 1 */
+ sSecond[] = "nd", /* 2 */
+ sThird[] = "rd"; /* 3 */
+ static const sal_Char* __READONLY_DATA aNumberTab[ 4 ] =
+ {
+ sAll, sFirst, sSecond, sThird
+ };
+
+ sal_Unicode c = rTxt.GetChar( nEndPos - 3 );
+ if( ( c -= '0' ) > 3 )
+ c = 0;
+
+ bChg = ( ((sal_Unicode)*((aNumberTab[ c ])+0)) ==
+ rTxt.GetChar( nEndPos - 2 ) &&
+ ((sal_Unicode)*((aNumberTab[ c ])+1)) ==
+ rTxt.GetChar( nEndPos - 1 )) ||
+ ( 3 < nEndPos - nSttPos &&
+ ( ((sal_Unicode)*(sAll+0)) == rTxt.GetChar( nEndPos - 2 ) &&
+ ((sal_Unicode)*(sAll+1)) == rTxt.GetChar( nEndPos - 1 )));
+
+ if( bChg )
+ {
+ // dann pruefe mal, ob alle bis zum Start alle Zahlen sind
+ for( xub_StrLen n = nEndPos - 3; nSttPos < n; )
+ if( !rCC.isDigit( rTxt, --n ) )
+ {
+ bChg = !rCC.isLetter( rTxt, n );
+ break;
+ }
+
+ if( bChg ) // dann setze mal das Escapement Attribut
+ {
+ SvxEscapementItem aSvxEscapementItem( DFLT_ESC_AUTO_SUPER,
+ DFLT_ESC_PROP, SID_ATTR_CHAR_ESCAPEMENT );
+ rDoc.SetAttr( nEndPos - 2, nEndPos,
+ SID_ATTR_CHAR_ESCAPEMENT,
+ aSvxEscapementItem);
+ }
+ }
+
+ }
+ return bChg;
+}
+
+
+BOOL SvxAutoCorrect::FnChgToEnEmDash(
+ SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nSttPos, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+ BOOL bRet = FALSE;
+ CharClass& rCC = GetCharClass( eLang );
+ if (eLang == LANGUAGE_SYSTEM)
+ eLang = GetAppLang();
+ bool bAlwaysUseEmDash = (cEmDash && (eLang == LANGUAGE_RUSSIAN || eLang == LANGUAGE_UKRAINIAN));
+
+ // ersetze " - " oder " --" durch "enDash"
+ if( cEnDash && 1 < nSttPos && 1 <= nEndPos - nSttPos )
+ {
+ sal_Unicode cCh = rTxt.GetChar( nSttPos );
+ if( '-' == cCh )
+ {
+ if( ' ' == rTxt.GetChar( nSttPos-1 ) &&
+ '-' == rTxt.GetChar( nSttPos+1 ))
+ {
+ xub_StrLen n;
+ for( n = nSttPos+2; n < nEndPos && lcl_IsInAsciiArr(
+ sImplSttSkipChars,(cCh = rTxt.GetChar( n )));
+ ++n )
+ ;
+
+ // found: " --[<AnySttChars>][A-z0-9]
+ if( rCC.isLetterNumeric( cCh ) )
+ {
+ for( n = nSttPos-1; n && lcl_IsInAsciiArr(
+ sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); )
+ ;
+
+ // found: "[A-z0-9][<AnyEndChars>] --[<AnySttChars>][A-z0-9]
+ if( rCC.isLetterNumeric( cCh ))
+ {
+ rDoc.Delete( nSttPos, nSttPos + 2 );
+ rDoc.Insert( nSttPos, bAlwaysUseEmDash ? cEmDash : cEnDash );
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+ else if( 3 < nSttPos &&
+ ' ' == rTxt.GetChar( nSttPos-1 ) &&
+ '-' == rTxt.GetChar( nSttPos-2 ))
+ {
+ xub_StrLen n, nLen = 1, nTmpPos = nSttPos - 2;
+ if( '-' == ( cCh = rTxt.GetChar( nTmpPos-1 )) )
+ {
+ --nTmpPos;
+ ++nLen;
+ cCh = rTxt.GetChar( nTmpPos-1 );
+ }
+ if( ' ' == cCh )
+ {
+ for( n = nSttPos; n < nEndPos && lcl_IsInAsciiArr(
+ sImplSttSkipChars,(cCh = rTxt.GetChar( n )));
+ ++n )
+ ;
+
+ // found: " - [<AnySttChars>][A-z0-9]
+ if( rCC.isLetterNumeric( cCh ) )
+ {
+ cCh = ' ';
+ for( n = nTmpPos-1; n && lcl_IsInAsciiArr(
+ sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); )
+ ;
+ // found: "[A-z0-9][<AnyEndChars>] - [<AnySttChars>][A-z0-9]
+ if( rCC.isLetterNumeric( cCh ))
+ {
+ rDoc.Delete( nTmpPos, nTmpPos + nLen );
+ rDoc.Insert( nTmpPos, bAlwaysUseEmDash ? cEmDash : cEnDash );
+ bRet = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ // Replace [A-z0-9]--[A-z0-9] double dash with "emDash" or "enDash".
+ // Finnish and Hungarian use enDash instead of emDash.
+ bool bEnDash = (eLang == LANGUAGE_HUNGARIAN || eLang == LANGUAGE_FINNISH);
+ if( ((cEmDash && !bEnDash) || (cEnDash && bEnDash)) && 4 <= nEndPos - nSttPos )
+ {
+ String sTmp( rTxt.Copy( nSttPos, nEndPos - nSttPos ) );
+ xub_StrLen nFndPos = sTmp.SearchAscii( "--" );
+ if( STRING_NOTFOUND != nFndPos && nFndPos &&
+ nFndPos + 2 < sTmp.Len() &&
+ ( rCC.isLetterNumeric( sTmp, nFndPos - 1 ) ||
+ lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nFndPos - 1 ) )) &&
+ ( rCC.isLetterNumeric( sTmp, nFndPos + 2 ) ||
+ lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nFndPos + 2 ) )))
+ {
+ nSttPos = nSttPos + nFndPos;
+ rDoc.Delete( nSttPos, nSttPos + 2 );
+ rDoc.Insert( nSttPos, (bEnDash ? cEnDash : cEmDash) );
+ bRet = TRUE;
+ }
+ }
+ return bRet;
+}
+
+
+BOOL SvxAutoCorrect::FnSetINetAttr( SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nSttPos, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+ String sURL( URIHelper::FindFirstURLInText( rTxt, nSttPos, nEndPos,
+ GetCharClass( eLang ) ));
+ BOOL bRet = 0 != sURL.Len();
+ if( bRet ) // also Attribut setzen:
+ rDoc.SetINetAttr( nSttPos, nEndPos, sURL );
+ return bRet;
+}
+
+
+BOOL SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+ // Bedingung:
+ // Am Anfang: _ oder * hinter Space mit nachfolgenden !Space
+ // Am Ende: _ oder * vor Space (Worttrenner?)
+
+ sal_Unicode c, cInsChar = rTxt.GetChar( nEndPos ); // unterstreichen oder fett
+ if( ++nEndPos != rTxt.Len() &&
+ !IsWordDelim( rTxt.GetChar( nEndPos ) ) )
+ return FALSE;
+
+ --nEndPos;
+
+ BOOL bAlphaNum = FALSE;
+ xub_StrLen nPos = nEndPos, nFndPos = STRING_NOTFOUND;
+ CharClass& rCC = GetCharClass( eLang );
+
+ while( nPos )
+ {
+ switch( c = rTxt.GetChar( --nPos ) )
+ {
+ case '_':
+ case '*':
+ if( c == cInsChar )
+ {
+ if( bAlphaNum && nPos+1 < nEndPos && ( !nPos ||
+ IsWordDelim( rTxt.GetChar( nPos-1 ))) &&
+ !IsWordDelim( rTxt.GetChar( nPos+1 )))
+ nFndPos = nPos;
+ else
+ // Bedingung ist nicht erfuellt, also abbrechen
+ nFndPos = STRING_NOTFOUND;
+ nPos = 0;
+ }
+ break;
+ default:
+ if( !bAlphaNum )
+ bAlphaNum = rCC.isLetterNumeric( rTxt, nPos );
+ }
+ }
+
+ if( STRING_NOTFOUND != nFndPos )
+ {
+ // ueber den gefundenen Bereich das Attribut aufspannen und
+ // das gefunde und am Ende stehende Zeichen loeschen
+ if( '*' == cInsChar ) // Fett
+ {
+ SvxWeightItem aSvxWeightItem( WEIGHT_BOLD, SID_ATTR_CHAR_WEIGHT );
+ rDoc.SetAttr( nFndPos + 1, nEndPos,
+ SID_ATTR_CHAR_WEIGHT,
+ aSvxWeightItem);
+ }
+ else // unterstrichen
+ {
+ SvxUnderlineItem aSvxUnderlineItem( UNDERLINE_SINGLE, SID_ATTR_CHAR_UNDERLINE );
+ rDoc.SetAttr( nFndPos + 1, nEndPos,
+ SID_ATTR_CHAR_UNDERLINE,
+ aSvxUnderlineItem);
+ }
+ rDoc.Delete( nEndPos, nEndPos + 1 );
+ rDoc.Delete( nFndPos, nFndPos + 1 );
+ }
+
+ return STRING_NOTFOUND != nFndPos;
+}
+
+
+BOOL SvxAutoCorrect::FnCptlSttSntnc( SvxAutoCorrDoc& rDoc,
+ const String& rTxt, BOOL bNormalPos,
+ xub_StrLen nSttPos, xub_StrLen nEndPos,
+ LanguageType eLang )
+{
+ // Grossbuchstabe am Satz-Anfang ??
+ if( !rTxt.Len() || nEndPos <= nSttPos )
+ return FALSE;
+
+ CharClass& rCC = GetCharClass( eLang );
+ String aText( rTxt );
+ const sal_Unicode *pStart = aText.GetBuffer(),
+ *pStr = pStart + nEndPos,
+ *pWordStt = 0,
+ *pDelim = 0;
+
+ BOOL bAtStart = FALSE, bPrevPara = FALSE;
+ do {
+ --pStr;
+ if( rCC.isLetter(
+ aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
+ {
+ if( !pWordStt )
+ pDelim = pStr+1;
+ pWordStt = pStr;
+ }
+ else if( pWordStt &&
+ !rCC.isDigit(
+ aText,
+ sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
+ {
+ if( lcl_IsInAsciiArr( sImplWordChars, *pStr ) &&
+ pWordStt - 1 == pStr &&
+ // --> FME 2005-02-14 #i38971#
+ // l'intallazione at beginning of paragraph. Replaced < by <=
+ (long)(pStart + 1) <= (long)pStr &&
+ // <--
+ rCC.isLetter(
+ aText,
+ sal::static_int_cast< xub_StrLen >( pStr-1 - pStart ) ) )
+ pWordStt = --pStr;
+ else
+ break;
+ }
+ } while( 0 == ( bAtStart = (pStart == pStr)) );
+
+
+ if( !pWordStt ||
+ rCC.isDigit(
+ aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) ||
+ IsUpperLetter(
+ rCC.getCharacterType(
+ aText,
+ sal::static_int_cast< xub_StrLen >( pWordStt - pStart ) ) ) ||
+ 0x1 == *pWordStt || 0x2 == *pWordStt )
+ return FALSE; // kein zu ersetzendes Zeichen, oder schon ok
+
+ // JP 27.10.97: wenn das Wort weniger als 3 Zeichen hat und der Trenner
+ // ein "Num"-Trenner ist, dann nicht ersetzen!
+ // Damit wird ein "a.", "a)", "a-a" nicht ersetzt!
+ if( *pDelim && 2 >= pDelim - pWordStt &&
+ lcl_IsInAsciiArr( ".-)>", *pDelim ) )
+ return FALSE;
+
+ if( !bAtStart ) // noch kein Absatz Anfang ?
+ {
+ if ( IsWordDelim( *pStr ) )
+ {
+ while( 0 == ( bAtStart = (pStart == pStr--) ) && IsWordDelim( *pStr ))
+ ;
+ }
+ // Asian full stop, full width full stop, full width exclamation mark
+ // and full width question marks are treated as word delimiters
+ else if ( 0x3002 != *pStr && 0xFF0E != *pStr && 0xFF01 != *pStr &&
+ 0xFF1F != *pStr )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ }
+
+ if( bAtStart ) // am Absatz Anfang ?
+ {
+ // Ueberpruefe den vorherigen Absatz, wenn es diesen gibt.
+ // Wenn ja, dann pruefe auf SatzTrenner am Ende.
+ const String* pPrevPara = rDoc.GetPrevPara( bNormalPos );
+ if( !pPrevPara )
+ {
+ // gueltiger Trenner -> Ersetze
+ String sChar( *pWordStt );
+ rCC.toUpper( sChar );
+ return sChar != *pWordStt &&
+ rDoc.Replace( xub_StrLen( pWordStt - pStart ), sChar );
+ }
+
+ aText = *pPrevPara;
+ bPrevPara = TRUE;
+ bAtStart = FALSE;
+ pStart = aText.GetBuffer();
+ pStr = pStart + aText.Len();
+
+ do { // alle Blanks ueberlesen
+ --pStr;
+ if( !IsWordDelim( *pStr ))
+ break;
+ } while( 0 == ( bAtStart = (pStart == pStr)) );
+
+ if( bAtStart )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ }
+
+ // bis hierhier wurde [ \t]+[A-Z0-9]+ gefunden. Test jetzt auf den
+ // Satztrenner. Es koennen alle 3 vorkommen, aber nicht mehrfach !!
+ const sal_Unicode* pExceptStt = 0;
+ if( !bAtStart )
+ {
+ BOOL bWeiter = TRUE;
+ int nFlag = C_NONE;
+ do {
+ switch( *pStr )
+ {
+ // Western and Asian full stop
+ case '.':
+ case 0x3002 :
+ case 0xFF0E :
+ {
+ if( nFlag & C_FULL_STOP )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ nFlag |= C_FULL_STOP;
+ pExceptStt = pStr;
+ }
+ break;
+ case '!':
+ case 0xFF01 :
+ {
+ if( nFlag & C_EXCLAMATION_MARK )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ nFlag |= C_EXCLAMATION_MARK;
+ }
+ break;
+ case '?':
+ case 0xFF1F :
+ {
+ if( nFlag & C_QUESTION_MARK)
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ nFlag |= C_QUESTION_MARK;
+ }
+ break;
+ default:
+ if( !nFlag )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ else
+ bWeiter = FALSE;
+ break;
+ }
+
+ if( bWeiter && pStr-- == pStart )
+ {
+// !!! wenn am Anfang, dann nie ersetzen.
+// if( !nFlag )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+// ++pStr;
+// break; // Schleife beenden
+ }
+ } while( bWeiter );
+ if( C_FULL_STOP != nFlag )
+ pExceptStt = 0;
+ }
+
+ if( 2 > ( pStr - pStart ) )
+ return FALSE;
+
+ if( !rCC.isLetterNumeric(
+ aText, sal::static_int_cast< xub_StrLen >( pStr-- - pStart ) ) )
+ {
+ BOOL bValid = FALSE, bAlphaFnd = FALSE;
+ const sal_Unicode* pTmpStr = pStr;
+ while( !bValid )
+ {
+ if( rCC.isDigit(
+ aText,
+ sal::static_int_cast< xub_StrLen >( pTmpStr - pStart ) ) )
+ {
+ bValid = TRUE;
+ pStr = pTmpStr - 1;
+ }
+ else if( rCC.isLetter(
+ aText,
+ sal::static_int_cast< xub_StrLen >(
+ pTmpStr - pStart ) ) )
+ {
+ if( bAlphaFnd )
+ {
+ bValid = TRUE;
+ pStr = pTmpStr;
+ }
+ else
+ bAlphaFnd = TRUE;
+ }
+ else if( bAlphaFnd || IsWordDelim( *pTmpStr ) )
+ break;
+
+ if( pTmpStr == pStart )
+ break;
+
+ --pTmpStr;
+ }
+
+ if( !bValid )
+ return FALSE; // kein gueltiger Trenner -> keine Ersetzung
+ }
+
+ BOOL bNumericOnly = '0' <= *(pStr+1) && *(pStr+1) <= '9';
+
+ // suche den Anfang vom Wort
+ while( !IsWordDelim( *pStr ))
+ {
+ if( bNumericOnly &&
+ rCC.isLetter(
+ aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
+ bNumericOnly = FALSE;
+
+ if( pStart == pStr )
+ break;
+
+ --pStr;
+ }
+
+ if( bNumericOnly ) // besteht nur aus Zahlen, dann nicht
+ return FALSE;
+
+ if( IsWordDelim( *pStr ))
+ ++pStr;
+
+ String sWord;
+
+ // ueberpruefe anhand der Exceptionliste
+ if( pExceptStt )
+ {
+ sWord = String(
+ pStr, sal::static_int_cast< xub_StrLen >( pExceptStt - pStr + 1 ) );
+ if( FindInCplSttExceptList(eLang, sWord) )
+ return FALSE;
+
+ // loesche alle nicht alpanum. Zeichen am Wortanfang/-ende und
+ // teste dann noch mal ( erkennt: "(min.", "/min.", usw.)
+ String sTmp( sWord );
+ while( sTmp.Len() &&
+ !rCC.isLetterNumeric( sTmp, 0 ) )
+ sTmp.Erase( 0, 1 );
+
+ // alle hinteren nicht alphanumerische Zeichen bis auf das
+ // Letzte entfernen
+ xub_StrLen nLen = sTmp.Len();
+ while( nLen && !rCC.isLetterNumeric( sTmp, nLen-1 ) )
+ --nLen;
+ if( nLen + 1 < sTmp.Len() )
+ sTmp.Erase( nLen + 1 );
+
+ if( sTmp.Len() && sTmp.Len() != sWord.Len() &&
+ FindInCplSttExceptList(eLang, sTmp))
+ return FALSE;
+
+ if(FindInCplSttExceptList(eLang, sWord, TRUE))
+ return FALSE;
+ }
+
+ // Ok, dann ersetze mal
+ sal_Unicode cSave = *pWordStt;
+ nSttPos = sal::static_int_cast< xub_StrLen >( pWordStt - rTxt.GetBuffer() );
+ String sChar( cSave );
+ rCC.toUpper( sChar );
+ BOOL bRet = sChar.GetChar(0) != cSave && rDoc.Replace( nSttPos, sChar );
+
+ // das Wort will vielleicht jemand haben
+ if( bRet && SaveWordCplSttLst & nFlags )
+ rDoc.SaveCpltSttWord( CptlSttSntnc, nSttPos, sWord, cSave );
+
+ return bRet;
+}
+//The method below is renamed from _GetQuote to GetQuote by BerryJia for Bug95846 Time:2002-8-13 15:50
+sal_Unicode SvxAutoCorrect::GetQuote( sal_Unicode cInsChar, BOOL bSttQuote,
+ LanguageType eLang ) const
+{
+ sal_Unicode cRet = bSttQuote ? ( '\"' == cInsChar
+ ? GetStartDoubleQuote()
+ : GetStartSingleQuote() )
+ : ( '\"' == cInsChar
+ ? GetEndDoubleQuote()
+ : GetEndSingleQuote() );
+ if( !cRet )
+ {
+ // dann ueber die Language das richtige Zeichen heraussuchen
+ if( LANGUAGE_NONE == eLang )
+ cRet = cInsChar;
+ else
+ {
+ LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang );
+ String sRet( bSttQuote
+ ? ( '\"' == cInsChar
+ ? rLcl.getDoubleQuotationMarkStart()
+ : rLcl.getQuotationMarkStart() )
+ : ( '\"' == cInsChar
+ ? rLcl.getDoubleQuotationMarkEnd()
+ : rLcl.getQuotationMarkEnd() ));
+ cRet = sRet.Len() ? sRet.GetChar( 0 ) : cInsChar;
+ }
+ }
+ return cRet;
+}
+
+void SvxAutoCorrect::InsertQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos,
+ sal_Unicode cInsChar, BOOL bSttQuote,
+ BOOL bIns )
+{
+ LanguageType eLang = rDoc.GetLanguage( nInsPos, FALSE );
+ sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang );
+
+ //JP 13.02.99: damit beim Undo das "einfuegte" Zeichen wieder erscheint,
+ // wird es erstmal eingefuegt und dann ueberschrieben
+ String sChg( cInsChar );
+ if( bIns )
+ rDoc.Insert( nInsPos, sChg );
+ else
+ rDoc.Replace( nInsPos, sChg );
+
+ //JP 13.08.97: Bug 42477 - bei doppelten Anfuehrungszeichen muss bei
+ // franzoesischer Sprache an Anfang ein Leerzeichen dahinter
+ // und am Ende ein Leerzeichen dahinter eingefuegt werden.
+ sChg = cRet;
+
+ if( '\"' == cInsChar )
+ {
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = GetAppLang();
+ switch( eLang )
+ {
+ case LANGUAGE_FRENCH:
+ case LANGUAGE_FRENCH_BELGIAN:
+ case LANGUAGE_FRENCH_CANADIAN:
+ case LANGUAGE_FRENCH_SWISS:
+ case LANGUAGE_FRENCH_LUXEMBOURG:
+ // JP 09.02.99: das zusaetzliche Zeichen immer per Insert einfuegen.
+ // Es ueberschreibt nichts!
+ {
+ String s( static_cast< sal_Unicode >(0xA0) );
+ // UNICODE code for no break space
+ if( rDoc.Insert( bSttQuote ? nInsPos+1 : nInsPos, s ))
+ {
+ if( !bSttQuote )
+ ++nInsPos;
+ }
+ }
+ break;
+ }
+ }
+
+ rDoc.Replace( nInsPos, sChg );
+}
+
+String SvxAutoCorrect::GetQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos,
+ sal_Unicode cInsChar, BOOL bSttQuote )
+{
+ LanguageType eLang = rDoc.GetLanguage( nInsPos, FALSE );
+ sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang );
+
+ String sRet( cRet );
+ //JP 13.08.97: Bug 42477 - bei doppelten Anfuehrungszeichen muss bei
+ // franzoesischer Sprache an Anfang ein Leerzeichen dahinter
+ // und am Ende ein Leerzeichen dahinter eingefuegt werden.
+ if( '\"' == cInsChar )
+ {
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = GetAppLang();
+ switch( eLang )
+ {
+ case LANGUAGE_FRENCH:
+ case LANGUAGE_FRENCH_BELGIAN:
+ case LANGUAGE_FRENCH_CANADIAN:
+ case LANGUAGE_FRENCH_SWISS:
+ case LANGUAGE_FRENCH_LUXEMBOURG:
+ if( bSttQuote )
+ sRet += ' ';
+ else
+ sRet.Insert( ' ', 0 );
+ break;
+ }
+ }
+ return sRet;
+}
+
+ULONG SvxAutoCorrect::AutoCorrect( SvxAutoCorrDoc& rDoc, const String& rTxt,
+ xub_StrLen nInsPos, sal_Unicode cChar,
+ BOOL bInsert )
+{
+ ULONG nRet = 0;
+ do{ // only for middle check loop !!
+ if( cChar )
+ {
+ //JP 10.02.97: doppelte Spaces verhindern
+ if( nInsPos && ' ' == cChar &&
+ IsAutoCorrFlag( IngnoreDoubleSpace ) &&
+ ' ' == rTxt.GetChar( nInsPos - 1 ) )
+ {
+ nRet = IngnoreDoubleSpace;
+ break;
+ }
+
+ BOOL bSingle = '\'' == cChar;
+ BOOL bIsReplaceQuote =
+ (IsAutoCorrFlag( ChgQuotes ) && ('\"' == cChar )) ||
+ (IsAutoCorrFlag( ChgSglQuotes ) && bSingle );
+ if( bIsReplaceQuote )
+ {
+ sal_Unicode cPrev;
+ BOOL bSttQuote = !nInsPos ||
+ IsWordDelim( ( cPrev = rTxt.GetChar( nInsPos-1 ))) ||
+// os: #56034# - Warum kein schliessendes Anfuehrungszeichen nach dem Bindestrich?
+// strchr( "-([{", cPrev ) ||
+ lcl_IsInAsciiArr( "([{", cPrev ) ||
+ ( cEmDash && cEmDash == cPrev ) ||
+ ( cEnDash && cEnDash == cPrev );
+
+ InsertQuote( rDoc, nInsPos, cChar, bSttQuote, bInsert );
+ nRet = bSingle ? ChgSglQuotes : ChgQuotes;
+ break;
+ }
+
+ if( bInsert )
+ rDoc.Insert( nInsPos, cChar );
+ else
+ rDoc.Replace( nInsPos, cChar );
+ }
+
+ if( !nInsPos )
+ break;
+
+ xub_StrLen nPos = nInsPos - 1;
+
+ // Bug 19286: nur direkt hinter dem "Wort" aufsetzen
+ if( IsWordDelim( rTxt.GetChar( nPos )))
+ break;
+
+ // automatisches Fett oder Unterstreichen setzen?
+ if( '*' == cChar || '_' == cChar )
+ {
+ if( IsAutoCorrFlag( ChgWeightUnderl ) &&
+ FnChgWeightUnderl( rDoc, rTxt, 0, nPos+1 ) )
+ nRet = ChgWeightUnderl;
+ break;
+ }
+
+ while( nPos && !IsWordDelim( rTxt.GetChar( --nPos )))
+ ;
+
+ // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort
+ // Kuerzel im Auto
+ xub_StrLen nCapLttrPos = nPos+1; // auf das 1. Zeichen
+ if( !nPos && !IsWordDelim( rTxt.GetChar( 0 )))
+ --nCapLttrPos; // Absatz Anfang und kein Blank !
+
+ LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, FALSE );
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = MsLangId::getSystemLanguage();
+ CharClass& rCC = GetCharClass( eLang );
+
+ // Bug 19285: Symbolzeichen nicht anfassen
+ if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nInsPos ))
+ break;
+
+ if( IsAutoCorrFlag( Autocorrect ) )
+ {
+ const String* pPara = 0;
+ const String** ppPara = IsAutoCorrFlag(CptlSttSntnc) ? &pPara : 0;
+
+ BOOL bChgWord = rDoc.ChgAutoCorrWord( nCapLttrPos, nInsPos,
+ *this, ppPara );
+ if( !bChgWord )
+ {
+ // JP 16.06.98: dann versuche mal alle !AlphaNum. Zeichen los zu
+ // werden und teste dann nochmals
+ //JP 22.04.99: Bug 63883 - entferne nur die "Klammern Start/-Anfaenge",
+ // alle anderen Zeichen muessen drin bleiben.
+ xub_StrLen nCapLttrPos1 = nCapLttrPos, nInsPos1 = nInsPos;
+ while( nCapLttrPos1 < nInsPos &&
+ lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos1 ) )
+ )
+ ++nCapLttrPos1;
+ while( nCapLttrPos1 < nInsPos1 && nInsPos1 &&
+ lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nInsPos1-1 ) )
+ )
+ --nInsPos1;
+
+ if( (nCapLttrPos1 != nCapLttrPos || nInsPos1 != nInsPos ) &&
+ nCapLttrPos1 < nInsPos1 &&
+ rDoc.ChgAutoCorrWord( nCapLttrPos1, nInsPos1, *this, ppPara ))
+ {
+ bChgWord = TRUE;
+ nCapLttrPos = nCapLttrPos1;
+ }
+ }
+
+ if( bChgWord )
+ {
+ nRet = Autocorrect;
+ if( pPara )
+ {
+ xub_StrLen nEnd = nCapLttrPos;
+ while( nEnd < pPara->Len() &&
+ !IsWordDelim( pPara->GetChar( nEnd )))
+ ++nEnd;
+
+ // Grossbuchstabe am Satz-Anfang ??
+ if( IsAutoCorrFlag( CptlSttSntnc ) &&
+ FnCptlSttSntnc( rDoc, *pPara, FALSE,
+ nCapLttrPos, nEnd, eLang ) )
+ nRet |= CptlSttSntnc;
+
+ if( IsAutoCorrFlag( ChgToEnEmDash ) &&
+ FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nEnd, eLang ) )
+ nRet |= ChgToEnEmDash;
+ }
+ break;
+ }
+ }
+
+ if( ( IsAutoCorrFlag( nRet = ChgFractionSymbol ) &&
+ FnChgFractionSymbol( rDoc, rTxt, nCapLttrPos, nInsPos ) ) ||
+ ( IsAutoCorrFlag( nRet = ChgOrdinalNumber ) &&
+ FnChgOrdinalNumber( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) ||
+ ( IsAutoCorrFlag( nRet = SetINetAttr ) &&
+ ( ' ' == cChar || '\t' == cChar || 0x0a == cChar || !cChar ) &&
+ FnSetINetAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) )
+ ;
+ else
+ {
+ nRet = 0;
+ // Grossbuchstabe am Satz-Anfang ??
+ if( IsAutoCorrFlag( CptlSttSntnc ) &&
+ FnCptlSttSntnc( rDoc, rTxt, TRUE, nCapLttrPos, nInsPos, eLang ) )
+ nRet |= CptlSttSntnc;
+
+ // Zwei Grossbuchstaben am Wort-Anfang ??
+ if( IsAutoCorrFlag( CptlSttWrd ) &&
+ FnCptlSttWrd( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) )
+ nRet |= CptlSttWrd;
+
+ if( IsAutoCorrFlag( ChgToEnEmDash ) &&
+ FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) )
+ nRet |= ChgToEnEmDash;
+ }
+
+ } while( FALSE );
+
+ if( nRet )
+ {
+ ULONG nHelpId = 0;
+ if( nRet & ( Autocorrect|CptlSttSntnc|CptlSttWrd|ChgToEnEmDash ) )
+ {
+ // von 0 - 15
+ if( nRet & ChgToEnEmDash )
+ nHelpId += 8;
+ if( nRet & Autocorrect )
+ nHelpId += 4;
+ if( nRet & CptlSttSntnc )
+ nHelpId += 2;
+ if( nRet & CptlSttWrd )
+ nHelpId += 1;
+ }
+ else
+ {
+ if( nRet & ChgQuotes) nHelpId = 16;
+ else if( nRet & ChgSglQuotes) nHelpId = 17;
+ else if( nRet & SetINetAttr) nHelpId = 18;
+ else if( nRet & IngnoreDoubleSpace) nHelpId = 19;
+ else if( nRet & ChgWeightUnderl) nHelpId = 20;
+ else if( nRet & ChgFractionSymbol ) nHelpId = 21;
+ else if( nRet & ChgOrdinalNumber) nHelpId = 22;
+ }
+
+ if( nHelpId )
+ {
+ nHelpId += HID_AUTOCORR_HELP_START - 1;
+ Application::GetHelp()->OpenHelpAgent( nHelpId );
+ }
+ }
+
+
+ return nRet;
+}
+
+SvxAutoCorrectLanguageLists& SvxAutoCorrect::_GetLanguageList(
+ LanguageType eLang )
+{
+ if( !pLangTable->IsKeyValid( ULONG( eLang )))
+ CreateLanguageFile( eLang, TRUE);
+ return *pLangTable->Seek( ULONG( eLang ) );
+}
+
+void SvxAutoCorrect::SaveCplSttExceptList( LanguageType eLang )
+{
+ if( pLangTable->IsKeyValid( ULONG( eLang )))
+ {
+ SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(ULONG(eLang));
+ if( pLists )
+ pLists->SaveCplSttExceptList();
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR("speichern einer leeren Liste?");
+ }
+#endif
+}
+
+void SvxAutoCorrect::SaveWrdSttExceptList(LanguageType eLang)
+{
+ if(pLangTable->IsKeyValid(ULONG(eLang)))
+ {
+ SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(ULONG(eLang));
+ if(pLists)
+ pLists->SaveWrdSttExceptList();
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ DBG_ERROR("speichern einer leeren Liste?");
+ }
+#endif
+}
+
+
+ // fuegt ein einzelnes Wort hinzu. Die Liste wird sofort
+ // in die Datei geschrieben!
+BOOL SvxAutoCorrect::AddCplSttException( const String& rNew,
+ LanguageType eLang )
+{
+ SvxAutoCorrectLanguageListsPtr pLists = 0;
+ //entweder die richtige Sprache ist vorhanden oder es kommt in die allg. Liste
+ if( pLangTable->IsKeyValid(ULONG(eLang)))
+ pLists = pLangTable->Seek(ULONG(eLang));
+ else if(pLangTable->IsKeyValid(ULONG(LANGUAGE_DONTKNOW))||
+ CreateLanguageFile(LANGUAGE_DONTKNOW, TRUE))
+ {
+ pLists = pLangTable->Seek(ULONG(LANGUAGE_DONTKNOW));
+ }
+ DBG_ASSERT(pLists, "keine Autokorrekturdatei");
+ return pLists->AddToCplSttExceptList(rNew);
+}
+
+
+ // fuegt ein einzelnes Wort hinzu. Die Liste wird sofort
+ // in die Datei geschrieben!
+BOOL SvxAutoCorrect::AddWrtSttException( const String& rNew,
+ LanguageType eLang )
+{
+ SvxAutoCorrectLanguageListsPtr pLists = 0;
+ //entweder die richtige Sprache ist vorhanden oder es kommt in die allg. Liste
+ if(pLangTable->IsKeyValid(ULONG(eLang)))
+ pLists = pLangTable->Seek(ULONG(eLang));
+ else if(pLangTable->IsKeyValid(ULONG(LANGUAGE_DONTKNOW))||
+ CreateLanguageFile(LANGUAGE_DONTKNOW, TRUE))
+ pLists = pLangTable->Seek(ULONG(LANGUAGE_DONTKNOW));
+ DBG_ASSERT(pLists, "keine Autokorrekturdatei");
+ return pLists->AddToWrdSttExceptList(rNew);
+}
+
+
+
+
+void SvxAutoCorrect::SetUserAutoCorrFileName( const String& rNew )
+{
+ if( sUserAutoCorrFile != rNew )
+ {
+ sUserAutoCorrFile = rNew;
+
+ // sind die Listen gesetzt sind, so muessen sie jetzt geloescht
+ // werden
+ lcl_ClearTable(*pLangTable);
+ nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad );
+ }
+}
+
+void SvxAutoCorrect::SetShareAutoCorrFileName( const String& rNew )
+{
+ if( sShareAutoCorrFile != rNew )
+ {
+ sShareAutoCorrFile = rNew;
+
+ // sind die Listen gesetzt sind, so muessen sie jetzt geloescht
+ // werden
+ lcl_ClearTable(*pLangTable);
+ nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad );
+ }
+}
+
+
+BOOL SvxAutoCorrect::GetPrevAutoCorrWord( SvxAutoCorrDoc& rDoc,
+ const String& rTxt, xub_StrLen nPos,
+ String& rWord ) const
+{
+ if( !nPos )
+ return FALSE;
+
+ xub_StrLen nEnde = nPos;
+
+ // dahinter muss ein Blank oder Tab folgen!
+ if( ( nPos < rTxt.Len() &&
+ !IsWordDelim( rTxt.GetChar( nPos ))) ||
+ IsWordDelim( rTxt.GetChar( --nPos )))
+ return FALSE;
+
+ while( nPos && !IsWordDelim( rTxt.GetChar( --nPos )))
+ ;
+
+ // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort
+ // Kuerzel im Auto
+ xub_StrLen nCapLttrPos = nPos+1; // auf das 1. Zeichen
+ if( !nPos && !IsWordDelim( rTxt.GetChar( 0 )))
+ --nCapLttrPos; // Absatz Anfang und kein Blank !
+
+ while( lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos )) )
+ if( ++nCapLttrPos >= nEnde )
+ return FALSE;
+
+ // Bug 19285: Symbolzeichen nicht anfassen
+ // Interresant erst ab 3 Zeichen
+ if( 3 > nEnde - nCapLttrPos )
+ return FALSE;
+
+ LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, FALSE );
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = MsLangId::getSystemLanguage();
+
+ SvxAutoCorrect* pThis = (SvxAutoCorrect*)this;
+ CharClass& rCC = pThis->GetCharClass( eLang );
+
+ if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nEnde ))
+ return FALSE;
+
+ rWord = rTxt.Copy( nCapLttrPos, nEnde - nCapLttrPos );
+ return TRUE;
+}
+
+BOOL SvxAutoCorrect::CreateLanguageFile( LanguageType eLang, BOOL bNewFile )
+{
+ DBG_ASSERT(!pLangTable->IsKeyValid(ULONG(eLang)), "Sprache ist bereits vorhanden");
+
+ String sUserDirFile( GetAutoCorrFileName( eLang, TRUE, FALSE )),
+ sShareDirFile( sUserDirFile );
+ SvxAutoCorrectLanguageListsPtr pLists = 0;
+
+ Time nMinTime( 0, 2 ), nAktTime, nLastCheckTime;
+ ULONG nFndPos;
+ if( TABLE_ENTRY_NOTFOUND !=
+ pLastFileTable->SearchKey( ULONG( eLang ), &nFndPos ) &&
+ ( nLastCheckTime.SetTime( pLastFileTable->GetObject( nFndPos )),
+ nLastCheckTime < nAktTime ) &&
+ ( nAktTime - nLastCheckTime ) < nMinTime )
+ {
+ // no need to test the file, because the last check is not older then
+ // 2 minutes.
+ if( bNewFile )
+ {
+ sShareDirFile = sUserDirFile;
+ pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile,
+ sUserDirFile, eLang );
+ pLangTable->Insert( ULONG(eLang), pLists );
+ pLastFileTable->Remove( ULONG( eLang ) );
+ }
+ }
+ else if( ( FStatHelper::IsDocument( sUserDirFile ) ||
+ FStatHelper::IsDocument( sShareDirFile =
+ GetAutoCorrFileName( eLang, FALSE, FALSE ) ) ) ||
+ ( sShareDirFile = sUserDirFile, bNewFile ))
+ {
+ pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile,
+ sUserDirFile, eLang );
+ pLangTable->Insert( ULONG(eLang), pLists );
+ pLastFileTable->Remove( ULONG( eLang ) );
+ }
+ else if( !bNewFile )
+ {
+ if( !pLastFileTable->Insert( ULONG( eLang ), nAktTime.GetTime() ))
+ pLastFileTable->Replace( ULONG( eLang ), nAktTime.GetTime() );
+ }
+ return pLists != 0;
+}
+
+BOOL SvxAutoCorrect::PutText( const String& rShort, const String& rLong,
+ LanguageType eLang )
+{
+ BOOL bRet = FALSE;
+ if( pLangTable->IsKeyValid( ULONG(eLang)) || CreateLanguageFile(eLang) )
+ bRet = pLangTable->Seek( ULONG(eLang) )->PutText(rShort, rLong);
+ return bRet;
+}
+
+
+ // - loesche einen Eintrag
+BOOL SvxAutoCorrect::DeleteText( const String& rShort, LanguageType eLang )
+{
+ BOOL bRet = FALSE;
+ if( pLangTable->IsKeyValid( ULONG( eLang )) )
+ bRet = pLangTable->Seek( ULONG( eLang ))->DeleteText( rShort );
+ return bRet;
+}
+
+
+ // - return den Ersetzungstext (nur fuer SWG-Format, alle anderen
+ // koennen aus der Wortliste herausgeholt werden!)
+BOOL SvxAutoCorrect::GetLongText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String& , String& )
+{
+ return FALSE;
+}
+
+ // - Text mit Attributierung (kann nur der SWG - SWG-Format!)
+BOOL SvxAutoCorrect::PutText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String&, SfxObjectShell&,
+ String& )
+{
+ return FALSE;
+}
+
+void EncryptBlockName_Imp( String& rName )
+{
+ xub_StrLen nLen, nPos = 1;
+ rName.Insert( '#', 0 );
+ sal_Unicode* pName = rName.GetBufferAccess();
+ for ( nLen = rName.Len(), ++pName; nPos < nLen; ++nPos, ++pName )
+ {
+ if( lcl_IsInAsciiArr( "!/:.\\", *pName ))
+ *pName &= 0x0f;
+ }
+}
+
+/* This code is copied from SwXMLTextBlocks::GeneratePackageName */
+void GeneratePackageName ( const String& rShort, String& rPackageName )
+{
+ rPackageName = rShort;
+ xub_StrLen nPos = 0;
+ sal_Unicode pDelims[] = { '!', '/', ':', '.', '\\', 0 };
+ ByteString sByte ( rPackageName, RTL_TEXTENCODING_UTF7);
+ rPackageName = String (sByte, RTL_TEXTENCODING_ASCII_US);
+ while( STRING_NOTFOUND != ( nPos = rPackageName.SearchChar( pDelims, nPos )))
+ {
+ rPackageName.SetChar( nPos, '_' );
+ ++nPos;
+ }
+}
+
+void DecryptBlockName_Imp( String& rName )
+{
+ if( '#' == rName.GetChar( 0 ) )
+ {
+ rName.Erase( 0, 1 );
+ sal_Unicode* pName = rName.GetBufferAccess();
+ xub_StrLen nLen, nPos;
+ for ( nLen = rName.Len(), nPos = 0; nPos < nLen; ++nPos, ++pName )
+ switch( *pName )
+ {
+ case 0x01: *pName = '!'; break;
+ case 0x0A: *pName = ':'; break;
+ case 0x0C: *pName = '\\'; break;
+ case 0x0E: *pName = '.'; break;
+ case 0x0F: *pName = '/'; break;
+ }
+ }
+}
+
+
+/* -----------------18.11.98 16:00-------------------
+ *
+ * --------------------------------------------------*/
+const SvxAutocorrWord* lcl_SearchWordsInList(
+ SvxAutoCorrectLanguageListsPtr pList, const String& rTxt,
+ xub_StrLen& rStt, xub_StrLen nEndPos, SvxAutoCorrDoc& )
+{
+ const SvxAutocorrWordList* pAutoCorrWordList = pList->GetAutocorrWordList();
+ TransliterationWrapper& rCmp = GetIgnoreTranslWrapper();
+ for( xub_StrLen nPos = 0; nPos < pAutoCorrWordList->Count(); ++nPos )
+ {
+ const SvxAutocorrWord* pFnd = (*pAutoCorrWordList)[ nPos ];
+ const String& rChk = pFnd->GetShort();
+ if( nEndPos >= rChk.Len() )
+ {
+ xub_StrLen nCalcStt = nEndPos - rChk.Len();
+ if( ( !nCalcStt || nCalcStt == rStt ||
+ ( nCalcStt < rStt &&
+ IsWordDelim( rTxt.GetChar(nCalcStt - 1 ) ))) )
+ {
+ String sWord( rTxt.GetBuffer() + nCalcStt, rChk.Len() );
+ if( rCmp.isEqual( rChk, sWord ))
+ {
+ rStt = nCalcStt;
+ return pFnd;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+// suche das oder die Worte in der ErsetzungsTabelle
+const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList(
+ const String& rTxt, xub_StrLen& rStt, xub_StrLen nEndPos,
+ SvxAutoCorrDoc& rDoc, LanguageType& rLang )
+{
+ LanguageType eLang = rLang;
+ const SvxAutocorrWord* pRet = 0;
+ if( LANGUAGE_SYSTEM == eLang )
+ eLang = MsLangId::getSystemLanguage();
+
+ // zuerst nach eLang suchen, dann nach der Obersprache
+ // US-Englisch -> Englisch und zuletzt in LANGUAGE_DONTKNOW
+
+ if( pLangTable->IsKeyValid( ULONG( eLang ) ) ||
+ CreateLanguageFile( eLang, FALSE ))
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(ULONG(eLang));
+ pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc );
+ if( pRet )
+ {
+ rLang = eLang;
+ return pRet;
+ }
+ }
+
+ // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen
+ ULONG nTmpKey1 = eLang & 0x7ff, // die Hauptsprache in vielen Faellen u.B. DE
+ nTmpKey2 = eLang & 0x3ff, // sonst z.B. EN
+ nTmp;
+
+ if( ((nTmp = nTmpKey1) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey1 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey1 ), FALSE ) )) ||
+ (( nTmp = nTmpKey2) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey2 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey2 ), FALSE ) )) )
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek( nTmp );
+ pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc);
+ if( pRet )
+ {
+ rLang = LanguageType( nTmp );
+ return pRet;
+ }
+ }
+ if( pLangTable->IsKeyValid( ULONG( LANGUAGE_DONTKNOW ) ) ||
+ CreateLanguageFile( LANGUAGE_DONTKNOW, FALSE ) )
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(ULONG(LANGUAGE_DONTKNOW));
+ pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos, rDoc);
+ if( pRet )
+ {
+ rLang = LANGUAGE_DONTKNOW;
+ return pRet;
+ }
+ }
+ return 0;
+}
+/* -----------------18.11.98 13:46-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang,
+ const String& sWord )
+{
+ //zuerst nach eLang suchen, dann nach der Obersprace US-Englisch -> Englisch
+ //und zuletzt in LANGUAGE_DONTKNOW
+ ULONG nTmpKey1 = eLang & 0x7ff; // die Hauptsprache in vielen Faellen u.B. DE
+ ULONG nTmpKey2 = eLang & 0x3ff; // sonst z.B. EN
+ String sTemp(sWord);
+ if( pLangTable->IsKeyValid( ULONG( eLang )) ||
+ CreateLanguageFile( eLang, FALSE ) )
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(ULONG(eLang));
+ String _sTemp(sWord);
+ if(pList->GetWrdSttExceptList()->Seek_Entry(&_sTemp))
+ return TRUE;
+
+ }
+ // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen
+ ULONG nTmp;
+ if( ((nTmp = nTmpKey1) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey1 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey1 ), FALSE ) )) ||
+ (( nTmp = nTmpKey2) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey2 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey2 ), FALSE ) )) )
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(nTmp);
+ if(pList->GetWrdSttExceptList()->Seek_Entry(&sTemp))
+ return TRUE;
+ }
+ if(pLangTable->IsKeyValid(ULONG(LANGUAGE_DONTKNOW))|| CreateLanguageFile(LANGUAGE_DONTKNOW, FALSE))
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pList = pLangTable->Seek(ULONG(LANGUAGE_DONTKNOW));
+ if(pList->GetWrdSttExceptList()->Seek_Entry(&sTemp))
+ return TRUE;
+ }
+ return FALSE;
+}
+/* -----------------18.11.98 14:28-------------------
+ *
+ * --------------------------------------------------*/
+BOOL lcl_FindAbbreviation( const SvStringsISortDtor* pList, const String& sWord)
+{
+ String sAbk( '~' );
+ USHORT nPos;
+ pList->Seek_Entry( &sAbk, &nPos );
+ if( nPos < pList->Count() )
+ {
+ String sLowerWord( sWord ); sLowerWord.ToLowerAscii();
+ const String* pAbk;
+ for( USHORT n = nPos;
+ n < pList->Count() &&
+ '~' == ( pAbk = (*pList)[ n ])->GetChar( 0 );
+ ++n )
+ {
+ // ~ und ~. sind nicht erlaubt!
+ if( 2 < pAbk->Len() && pAbk->Len() - 1 <= sWord.Len() )
+ {
+ String sLowerAbk( *pAbk ); sLowerAbk.ToLowerAscii();
+ for( xub_StrLen i = sLowerAbk.Len(), ii = sLowerWord.Len(); i; )
+ {
+ if( !--i ) // stimmt ueberein
+ return TRUE;
+
+ if( sLowerAbk.GetChar( i ) != sLowerWord.GetChar( --ii ))
+ break;
+ }
+ }
+ }
+ }
+ DBG_ASSERT( !(nPos && '~' == (*pList)[ --nPos ]->GetChar( 0 ) ),
+ "falsch sortierte ExeptionListe?" );
+ return FALSE;
+}
+/* -----------------18.11.98 14:49-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang,
+ const String& sWord, BOOL bAbbreviation)
+{
+ //zuerst nach eLang suchen, dann nach der Obersprace US-Englisch -> Englisch
+ //und zuletzt in LANGUAGE_DONTKNOW
+ ULONG nTmpKey1 = eLang & 0x7ff; // die Hauptsprache in vielen Faellen u.B. DE
+ ULONG nTmpKey2 = eLang & 0x3ff; // sonst z.B. EN
+ String sTemp( sWord );
+ if( pLangTable->IsKeyValid( ULONG( eLang )) ||
+ CreateLanguageFile( eLang, FALSE ))
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(ULONG(eLang));
+ const SvStringsISortDtor* pList = pLists->GetCplSttExceptList();
+ if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord)
+ : pList->Seek_Entry( &sTemp ) )
+ return TRUE;
+ }
+ // wenn es hier noch nicht gefunden werden konnte, dann weitersuchen
+ ULONG nTmp;
+
+ if( ((nTmp = nTmpKey1) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey1 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey1 ), FALSE ) )) ||
+ (( nTmp = nTmpKey2) != (ULONG)eLang &&
+ ( pLangTable->IsKeyValid( nTmpKey2 ) ||
+ CreateLanguageFile( LanguageType( nTmpKey2 ), FALSE ) )) )
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(nTmp);
+ const SvStringsISortDtor* pList = pLists->GetCplSttExceptList();
+ if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord)
+ : pList->Seek_Entry( &sTemp ) )
+ return TRUE;
+ }
+ if(pLangTable->IsKeyValid(ULONG(LANGUAGE_DONTKNOW))|| CreateLanguageFile(LANGUAGE_DONTKNOW, FALSE))
+ {
+ //die Sprache ist vorhanden - also her damit
+ SvxAutoCorrectLanguageListsPtr pLists = pLangTable->Seek(LANGUAGE_DONTKNOW);
+ const SvStringsISortDtor* pList = pLists->GetCplSttExceptList();
+ if(bAbbreviation ? lcl_FindAbbreviation( pList, sWord)
+ : pList->Seek_Entry( &sTemp ) )
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+/* -----------------20.11.98 11:53-------------------
+ *
+ * --------------------------------------------------*/
+String SvxAutoCorrect::GetAutoCorrFileName( LanguageType eLang,
+ BOOL bNewFile, BOOL bTst ) const
+{
+ String sRet, sExt( MsLangId::convertLanguageToIsoString( eLang ) );
+ sExt.Insert('_', 0);
+ sExt.AppendAscii( ".dat" );
+ if( bNewFile )
+ ( sRet = sUserAutoCorrFile ) += sExt;
+ else if( !bTst )
+ ( sRet = sShareAutoCorrFile ) += sExt;
+ else
+ {
+ // test first in the user directory - if not exist, then
+ ( sRet = sUserAutoCorrFile ) += sExt;
+ if( !FStatHelper::IsDocument( sRet ))
+ ( sRet = sShareAutoCorrFile ) += sExt;
+ }
+ return sRet;
+}
+
+/* -----------------18.11.98 11:16-------------------
+ *
+ * --------------------------------------------------*/
+SvxAutoCorrectLanguageLists::SvxAutoCorrectLanguageLists(
+ SvxAutoCorrect& rParent,
+ const String& rShareAutoCorrectFile,
+ const String& rUserAutoCorrectFile,
+ LanguageType eLang)
+: sShareAutoCorrFile( rShareAutoCorrectFile ),
+ sUserAutoCorrFile( rUserAutoCorrectFile ),
+ eLanguage(eLang),
+ pCplStt_ExcptLst( 0 ),
+ pWrdStt_ExcptLst( 0 ),
+ pAutocorr_List( 0 ),
+ rAutoCorrect(rParent),
+ nFlags(0)
+{
+}
+
+/* -----------------18.11.98 11:16-------------------
+ *
+ * --------------------------------------------------*/
+SvxAutoCorrectLanguageLists::~SvxAutoCorrectLanguageLists()
+{
+ delete pCplStt_ExcptLst;
+ delete pWrdStt_ExcptLst;
+ delete pAutocorr_List;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrectLanguageLists::IsFileChanged_Imp()
+{
+ // nur alle 2 Minuten aufs FileSystem zugreifen um den
+ // Dateistempel zu ueberpruefen
+ BOOL bRet = FALSE;
+
+ Time nMinTime( 0, 2 );
+ Time nAktTime;
+ if( aLastCheckTime > nAktTime || // ueberlauf ?
+ ( nAktTime -= aLastCheckTime ) > nMinTime ) // min Zeit vergangen
+ {
+ Date aTstDate; Time aTstTime;
+ if( FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
+ &aTstDate, &aTstTime ) &&
+ ( aModifiedDate != aTstDate || aModifiedTime != aTstTime ))
+ {
+ bRet = TRUE;
+ // dann mal schnell alle Listen entfernen!
+ if( CplSttLstLoad & nFlags && pCplStt_ExcptLst )
+ delete pCplStt_ExcptLst, pCplStt_ExcptLst = 0;
+ if( WrdSttLstLoad & nFlags && pWrdStt_ExcptLst )
+ delete pWrdStt_ExcptLst, pWrdStt_ExcptLst = 0;
+ if( ChgWordLstLoad & nFlags && pAutocorr_List )
+ delete pAutocorr_List, pAutocorr_List = 0;
+ nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad );
+ }
+ aLastCheckTime = Time();
+ }
+ return bRet;
+}
+
+void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp(
+ SvStringsISortDtor*& rpLst,
+ const sal_Char* pStrmName,
+ SotStorageRef& rStg)
+{
+ if( rpLst )
+ rpLst->DeleteAndDestroy( 0, rpLst->Count() );
+ else
+ rpLst = new SvStringsISortDtor( 16, 16 );
+
+ {
+ String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 );
+ String sTmp( sStrmName );
+
+ if( rStg.Is() && rStg->IsStream( sStrmName ) )
+ {
+ SvStorageStreamRef xStrm = rStg->OpenSotStream( sTmp,
+ ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE ) );
+ if( SVSTREAM_OK != xStrm->GetError())
+ {
+ xStrm.Clear();
+ rStg.Clear();
+ RemoveStream_Imp( sStrmName );
+ }
+ else
+ {
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ DBG_ASSERT( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = sStrmName;
+
+ xStrm->Seek( 0L );
+ xStrm->SetBufferSize( 8 * 1024 );
+ aParserInput.aInputStream = new utl::OInputStreamWrapper( *xStrm );
+
+ // get parser
+ uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance(
+ OUString::createFromAscii("com.sun.star.xml.sax.Parser") );
+ DBG_ASSERT( xXMLParser.is(),
+ "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" );
+ if( !xXMLParser.is() )
+ {
+ // Maybe throw an exception?
+ }
+
+ // get filter
+ // #110680#
+ // uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLExceptionListImport ( *rpLst );
+ uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLExceptionListImport ( xServiceFactory, *rpLst );
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY );
+ xParser->setDocumentHandler( xFilter );
+
+ // parse
+ try
+ {
+ xParser->parseStream( aParserInput );
+ }
+ catch( xml::sax::SAXParseException& )
+ {
+ // re throw ?
+ }
+ catch( xml::sax::SAXException& )
+ {
+ // re throw ?
+ }
+ catch( io::IOException& )
+ {
+ // re throw ?
+ }
+ }
+ }
+
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+ }
+
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::SaveExceptList_Imp(
+ const SvStringsISortDtor& rLst,
+ const sal_Char* pStrmName,
+ SotStorageRef &rStg,
+ BOOL bConvert )
+{
+ if( rStg.Is() )
+ {
+ String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 );
+ if( !rLst.Count() )
+ {
+ rStg->Remove( sStrmName );
+ rStg->Commit();
+ }
+ else
+ {
+ SotStorageStreamRef xStrm = rStg->OpenSotStream( sStrmName,
+ ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) );
+ if( xStrm.Is() )
+ {
+ xStrm->SetSize( 0 );
+ xStrm->SetBufferSize( 8192 );
+ String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
+ OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
+ uno::Any aAny;
+ aAny <<= aMime;
+ xStrm->SetProperty( aPropName, aAny );
+
+
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ DBG_ASSERT( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ uno::Reference < XInterface > xWriter (xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer"))));
+ DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing");
+ uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *xStrm );
+ uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
+ xSrc->setOutputStream(xOut);
+
+ uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY);
+
+ // #110680#
+ // SvXMLExceptionListExport aExp(rLst, sStrmName, xHandler);
+ SvXMLExceptionListExport aExp( xServiceFactory, rLst, sStrmName, xHandler );
+
+ aExp.exportDoc( XML_BLOCK_LIST );
+
+ xStrm->Commit();
+ if( xStrm->GetError() == SVSTREAM_OK )
+ {
+ xStrm.Clear();
+ if (!bConvert)
+ {
+ rStg->Commit();
+ if( SVSTREAM_OK != rStg->GetError() )
+ {
+ rStg->Remove( sStrmName );
+ rStg->Commit();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+SvxAutocorrWordList* SvxAutoCorrectLanguageLists::LoadAutocorrWordList()
+{
+ if( pAutocorr_List )
+ pAutocorr_List->DeleteAndDestroy( 0, pAutocorr_List->Count() );
+ else
+ pAutocorr_List = new SvxAutocorrWordList( 16, 16 );
+
+ SvStringsDtor aRemoveArr;
+ try
+ {
+ uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sShareAutoCorrFile, embed::ElementModes::READ );
+ String aXMLWordListName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 );
+ uno::Reference < io::XStream > xStrm = xStg->openStreamElement( aXMLWordListName, embed::ElementModes::READ );
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory = comphelper::getProcessServiceFactory();
+
+ xml::sax::InputSource aParserInput;
+ aParserInput.sSystemId = aXMLWordListName;
+ aParserInput.aInputStream = xStrm->getInputStream();
+
+ // get parser
+ uno::Reference< XInterface > xXMLParser = xServiceFactory->createInstance( OUString::createFromAscii("com.sun.star.xml.sax.Parser") );
+ DBG_ASSERT( xXMLParser.is(), "XMLReader::Read: com.sun.star.xml.sax.Parser service missing" );
+ if( xXMLParser.is() )
+ {
+ uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLAutoCorrectImport( xServiceFactory, pAutocorr_List, rAutoCorrect, xStg );
+
+ // connect parser and filter
+ uno::Reference< xml::sax::XParser > xParser( xXMLParser, UNO_QUERY );
+ xParser->setDocumentHandler( xFilter );
+
+ // parse
+ xParser->parseStream( aParserInput );
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+
+ return pAutocorr_List;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+
+void SvxAutoCorrectLanguageLists::SetAutocorrWordList( SvxAutocorrWordList* pList )
+{
+ if( pAutocorr_List && pList != pAutocorr_List )
+ delete pAutocorr_List;
+ pAutocorr_List = pList;
+ if( !pAutocorr_List )
+ {
+ DBG_ASSERT( !this, "keine gueltige Liste" );
+ pAutocorr_List = new SvxAutocorrWordList( 16, 16 );
+ }
+ nFlags |= ChgWordLstLoad;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+const SvxAutocorrWordList* SvxAutoCorrectLanguageLists::GetAutocorrWordList()
+{
+ if( !( ChgWordLstLoad & nFlags ) || IsFileChanged_Imp() )
+ SetAutocorrWordList( LoadAutocorrWordList() );
+ return pAutocorr_List;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetCplSttExceptList()
+{
+ if( !( CplSttLstLoad & nFlags ) || IsFileChanged_Imp() )
+ SetCplSttExceptList( LoadCplSttExceptList() );
+ return pCplStt_ExcptLst;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const String& rNew)
+{
+ String* pNew = new String( rNew );
+ if( rNew.Len() && GetCplSttExceptList()->Insert( pNew ) )
+ {
+ MakeUserStorage_Impl();
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+
+ SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
+
+ xStg = 0;
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+ }
+ else
+ delete pNew, pNew = 0;
+ return 0 != pNew;
+}
+/* -----------------18.11.98 15:20-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrectLanguageLists::AddToWrdSttExceptList(const String& rNew)
+{
+ String* pNew = new String( rNew );
+ SvStringsISortDtor* pExceptList = LoadWrdSttExceptList();
+ if( rNew.Len() && pExceptList && pExceptList->Insert( pNew ) )
+ {
+ MakeUserStorage_Impl();
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+
+ SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
+
+ xStg = 0;
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+ }
+ else
+ delete pNew, pNew = 0;
+ return 0 != pNew;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList()
+{
+ SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, TRUE );
+ String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) );
+ if( xStg.Is() && xStg->IsContained( sTemp ) )
+ LoadXMLExceptList_Imp( pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
+
+ return pCplStt_ExcptLst;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::SaveCplSttExceptList()
+{
+ MakeUserStorage_Impl();
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+
+ SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
+
+ xStg = 0;
+
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::SetCplSttExceptList( SvStringsISortDtor* pList )
+{
+ if( pCplStt_ExcptLst && pList != pCplStt_ExcptLst )
+ delete pCplStt_ExcptLst;
+
+ pCplStt_ExcptLst = pList;
+ if( !pCplStt_ExcptLst )
+ {
+ DBG_ASSERT( !this, "keine gueltige Liste" );
+ pCplStt_ExcptLst = new SvStringsISortDtor( 16, 16 );
+ }
+ nFlags |= CplSttLstLoad;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWrdSttExceptList()
+{
+ SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, TRUE );
+ String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) );
+ if( xStg.Is() && xStg->IsContained( sTemp ) )
+ LoadXMLExceptList_Imp( pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
+ return pWrdStt_ExcptLst;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::SaveWrdSttExceptList()
+{
+ MakeUserStorage_Impl();
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+
+ SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
+
+ xStg = 0;
+ // Zeitstempel noch setzen
+ FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
+ &aModifiedDate, &aModifiedTime );
+ aLastCheckTime = Time();
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::SetWrdSttExceptList( SvStringsISortDtor* pList )
+{
+ if( pWrdStt_ExcptLst && pList != pWrdStt_ExcptLst )
+ delete pWrdStt_ExcptLst;
+ pWrdStt_ExcptLst = pList;
+ if( !pWrdStt_ExcptLst )
+ {
+ DBG_ASSERT( !this, "keine gueltige Liste" );
+ pWrdStt_ExcptLst = new SvStringsISortDtor( 16, 16 );
+ }
+ nFlags |= WrdSttLstLoad;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetWrdSttExceptList()
+{
+ if( !( WrdSttLstLoad & nFlags ) || IsFileChanged_Imp() )
+ SetWrdSttExceptList( LoadWrdSttExceptList() );
+ return pWrdStt_ExcptLst;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+void SvxAutoCorrectLanguageLists::RemoveStream_Imp( const String& rName )
+{
+ if( sShareAutoCorrFile != sUserAutoCorrFile )
+ {
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+ if( xStg.Is() && SVSTREAM_OK == xStg->GetError() &&
+ xStg->IsStream( rName ) )
+ {
+ xStg->Remove( rName );
+ xStg->Commit();
+
+ xStg = 0;
+ }
+ }
+}
+
+void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl()
+{
+ // The conversion needs to happen if the file is already in the user
+ // directory and is in the old format. Additionally it needs to
+ // happen when the file is being copied from share to user.
+
+ sal_Bool bError = sal_False, bConvert = sal_False, bCopy = sal_False;
+ INetURLObject aDest;
+ INetURLObject aSource;
+
+// String sDestPath = sUserAutoCorrFile.Copy ( 0, sUserAutoCorrFile.Len()-3);
+// sDestPath.AppendAscii ("bak");
+
+
+ if (sUserAutoCorrFile != sShareAutoCorrFile )
+ {
+ aSource = INetURLObject ( sShareAutoCorrFile ); //aSource.setFSysPath ( sShareAutoCorrFile, INetURLObject::FSYS_DETECT );
+ aDest = INetURLObject ( sUserAutoCorrFile );
+ if ( SotStorage::IsOLEStorage ( sShareAutoCorrFile ) )
+ {
+ aDest.SetExtension ( String::CreateFromAscii ( "bak" ) );
+ bConvert = sal_True;
+ }
+ bCopy = sal_True;
+ }
+ else if ( SotStorage::IsOLEStorage ( sUserAutoCorrFile ) )
+ {
+ aSource = INetURLObject ( sUserAutoCorrFile );
+ aDest = INetURLObject ( sUserAutoCorrFile );
+ aDest.SetExtension ( String::CreateFromAscii ( "bak" ) );
+ bCopy = bConvert = sal_True;
+ }
+ if (bCopy)
+ {
+ try
+ {
+ String sMain(aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ));
+ sal_Unicode cSlash = '/';
+ xub_StrLen nSlashPos = sMain.SearchBackward(cSlash);
+ sMain.Erase(nSlashPos);
+ ::ucbhelper::Content aNewContent( sMain, uno::Reference< XCommandEnvironment > ());
+ Any aAny;
+ TransferInfo aInfo;
+ aInfo.NameClash = NameClash::OVERWRITE;
+ aInfo.NewTitle = aDest.GetName();
+ aInfo.SourceURL = aSource.GetMainURL( INetURLObject::DECODE_TO_IURI );
+ aInfo.MoveData = FALSE;
+ aAny <<= aInfo;
+ aNewContent.executeCommand( OUString ( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ), aAny);
+ }
+ catch (...)
+ {
+ bError = sal_True;
+ }
+ }
+ if (bConvert && !bError)
+ {
+ SotStorageRef xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), STREAM_READ, TRUE );
+ SotStorageRef xDstStg = new SotStorage( sUserAutoCorrFile, STREAM_WRITE, TRUE );
+
+ if( xSrcStg.Is() && xDstStg.Is() )
+ {
+ String sWord ( RTL_CONSTASCII_USTRINGPARAM ( pImplWrdStt_ExcptLstStr ) );
+ String sSentence ( RTL_CONSTASCII_USTRINGPARAM ( pImplCplStt_ExcptLstStr ) );
+ String sXMLWord ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) );
+ String sXMLSentence ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) );
+ SvStringsISortDtor *pTmpWordList = NULL;
+
+ if (xSrcStg->IsContained( sXMLWord ) )
+ LoadXMLExceptList_Imp( pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xSrcStg );
+
+ if (pTmpWordList)
+ {
+ SaveExceptList_Imp( *pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xDstStg, TRUE );
+ pTmpWordList->DeleteAndDestroy( 0, pTmpWordList->Count() );
+ pTmpWordList = NULL;
+ }
+
+
+ if (xSrcStg->IsContained( sXMLSentence ) )
+ LoadXMLExceptList_Imp( pTmpWordList, pXMLImplCplStt_ExcptLstStr, xSrcStg );
+
+ if (pTmpWordList)
+ {
+ SaveExceptList_Imp( *pTmpWordList, pXMLImplCplStt_ExcptLstStr, xDstStg, TRUE );
+ pTmpWordList->DeleteAndDestroy( 0, pTmpWordList->Count() );
+ }
+
+ GetAutocorrWordList();
+ MakeBlocklist_Imp( *xDstStg );
+ // xDstStg is committed in MakeBlocklist_Imp
+ /*xSrcStg->CopyTo( &xDstStg );*/
+ sShareAutoCorrFile = sUserAutoCorrFile;
+ xDstStg = 0;
+ try
+ {
+ ::ucbhelper::Content aContent ( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), uno::Reference < XCommandEnvironment > ());
+ aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "delete" ) ), makeAny ( sal_Bool (sal_True ) ) );
+ }
+ catch (...)
+ {
+ }
+ }
+ }
+ else if( bCopy && !bError )
+ sShareAutoCorrFile = sUserAutoCorrFile;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrectLanguageLists::MakeBlocklist_Imp( SvStorage& rStg )
+{
+ String sStrmName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 );
+ BOOL bRet = TRUE, bRemove = !pAutocorr_List || !pAutocorr_List->Count();
+ if( !bRemove )
+ {
+ /*
+ if ( rStg.IsContained( sStrmName) )
+ {
+ rStg.Remove ( sStrmName );
+ rStg.Commit();
+ }
+ */
+ SvStorageStreamRef refList = rStg.OpenSotStream( sStrmName,
+ ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) );
+ if( refList.Is() )
+ {
+ refList->SetSize( 0 );
+ refList->SetBufferSize( 8192 );
+ String aPropName( String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM("MediaType") ) );
+ OUString aMime( RTL_CONSTASCII_USTRINGPARAM("text/xml") );
+ uno::Any aAny;
+ aAny <<= aMime;
+ refList->SetProperty( aPropName, aAny );
+
+ uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
+ comphelper::getProcessServiceFactory();
+ DBG_ASSERT( xServiceFactory.is(),
+ "XMLReader::Read: got no service manager" );
+ if( !xServiceFactory.is() )
+ {
+ // Throw an exception ?
+ }
+
+ uno::Reference < XInterface > xWriter (xServiceFactory->createInstance(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Writer"))));
+ DBG_ASSERT(xWriter.is(),"com.sun.star.xml.sax.Writer service missing");
+ uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *refList );
+ uno::Reference<io::XActiveDataSource> xSrc(xWriter, uno::UNO_QUERY);
+ xSrc->setOutputStream(xOut);
+
+ uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY);
+
+ // #110680#
+ // SvXMLAutoCorrectExport aExp(pAutocorr_List, sStrmName, xHandler);
+ SvXMLAutoCorrectExport aExp( xServiceFactory, pAutocorr_List, sStrmName, xHandler );
+
+ aExp.exportDoc( XML_BLOCK_LIST );
+
+ refList->Commit();
+ bRet = SVSTREAM_OK == refList->GetError();
+ if( bRet )
+ {
+ refList.Clear();
+ rStg.Commit();
+ if( SVSTREAM_OK != rStg.GetError() )
+ {
+ bRemove = TRUE;
+ bRet = FALSE;
+ }
+ }
+
+ /*
+ refList->SetSize( 0 );
+ refList->SetBufferSize( 8192 );
+ rtl_TextEncoding eEncoding = gsl_getSystemTextEncoding();
+
+ String aDummy; // Erkennungszeichen fuer neue Streams
+ refList->WriteByteString( aDummy, RTL_TEXTENCODING_MS_1252 )
+ << (BYTE) 4 // Laenge des Headers (ohne den Leerstring)
+ << (USHORT)WORDLIST_VERSION_358 // Version des Streams
+ << (BYTE)eEncoding; // der Zeichensatz
+
+ for( USHORT i = 0; i < pAutocorr_List->Count() &&
+ SVSTREAM_OK == refList->GetError(); ++i )
+ {
+ SvxAutocorrWord* p = pAutocorr_List->GetObject( i );
+ refList->WriteByteString( p->GetShort(), eEncoding ).
+ WriteByteString( p->IsTextOnly()
+ ? p->GetLong()
+ : p->GetShort(), eEncoding );
+ }
+ refList->Commit();
+ bRet = SVSTREAM_OK == refList->GetError();
+ if( bRet )
+ {
+ refList.Clear();
+ rStg.Commit();
+ if( SVSTREAM_OK != rStg.GetError() )
+ {
+ bRemove = TRUE;
+ bRet = FALSE;
+ }
+ }
+ */
+ }
+ else
+ bRet = FALSE;
+ }
+
+ if( bRemove )
+ {
+ rStg.Remove( sStrmName );
+ rStg.Commit();
+ }
+
+ return bRet;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+BOOL SvxAutoCorrectLanguageLists::PutText( const String& rShort,
+ const String& rLong )
+{
+ // erstmal akt. Liste besorgen!
+ GetAutocorrWordList();
+
+ MakeUserStorage_Impl();
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+
+ BOOL bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError();
+
+/* if( bRet )
+ {
+ // PutText( *xStg, rShort );
+ }
+*/
+ // die Wortliste aktualisieren
+ if( bRet )
+ {
+ USHORT nPos;
+ SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, rLong, TRUE );
+ if( pAutocorr_List->Seek_Entry( pNew, &nPos ) )
+ {
+ if( !(*pAutocorr_List)[ nPos ]->IsTextOnly() )
+ {
+ // dann ist der Storage noch zu entfernen
+ String sStgNm( rShort );
+ if (xStg->IsOLEStorage())
+ EncryptBlockName_Imp( sStgNm );
+ else
+ GeneratePackageName ( rShort, sStgNm);
+
+ if( xStg->IsContained( sStgNm ) )
+ xStg->Remove( sStgNm );
+ }
+ pAutocorr_List->DeleteAndDestroy( nPos );
+ }
+
+ if( pAutocorr_List->Insert( pNew ) )
+ {
+ bRet = MakeBlocklist_Imp( *xStg );
+ xStg = 0;
+ }
+ else
+ {
+ delete pNew;
+ bRet = FALSE;
+ }
+ }
+ return bRet;
+}
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+ // - Text mit Attributierung (kann nur der SWG - SWG-Format!)
+BOOL SvxAutoCorrectLanguageLists::PutText( const String& rShort,
+ SfxObjectShell& rShell )
+{
+ // erstmal akt. Liste besorgen!
+ GetAutocorrWordList();
+
+ MakeUserStorage_Impl();
+
+ BOOL bRet = FALSE;
+ String sLong;
+ try
+ {
+ uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sUserAutoCorrFile, embed::ElementModes::READWRITE );
+// String aName( rShort );
+// EncryptBlockName_Imp( aName );
+// bRet = PutText( *xStg, aName, rShell, sLong );
+ bRet = rAutoCorrect.PutText( xStg, sUserAutoCorrFile, rShort, rShell, sLong );
+ xStg = 0;
+
+ // die Wortliste aktualisieren
+ if( bRet )
+ {
+ SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, sLong, FALSE );
+ if( pAutocorr_List->Insert( pNew ) )
+ {
+ SotStorageRef xStor = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+ MakeBlocklist_Imp( *xStor );
+ }
+ else
+ delete pNew;
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ return bRet;
+}
+
+/* -----------------18.11.98 11:26-------------------
+ *
+ * --------------------------------------------------*/
+ // - loesche einen Eintrag
+BOOL SvxAutoCorrectLanguageLists::DeleteText( const String& rShort )
+{
+ // erstmal akt. Liste besorgen!
+ GetAutocorrWordList();
+
+ MakeUserStorage_Impl();
+
+ SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, TRUE );
+ BOOL bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError();
+ if( bRet )
+ {
+ USHORT nPos;
+ SvxAutocorrWord aTmp( rShort, rShort );
+ if( pAutocorr_List->Seek_Entry( &aTmp, &nPos ) )
+ {
+ SvxAutocorrWord* pFnd = (*pAutocorr_List)[ nPos ];
+ if( !pFnd->IsTextOnly() )
+ {
+ String aName( rShort );
+ if (xStg->IsOLEStorage())
+ EncryptBlockName_Imp( aName );
+ else
+ GeneratePackageName ( rShort, aName );
+ if( xStg->IsContained( aName ) )
+ {
+ xStg->Remove( aName );
+ bRet = xStg->Commit();
+ }
+
+ }
+ // die Wortliste aktualisieren
+ pAutocorr_List->DeleteAndDestroy( nPos );
+ MakeBlocklist_Imp( *xStg );
+ xStg = 0;
+ }
+ else
+ bRet = FALSE;
+ }
+ return bRet;
+}
diff --git a/editeng/source/misc/swafopt.cxx b/editeng/source/misc/swafopt.cxx
new file mode 100644
index 0000000000..e6dcd15972
--- /dev/null
+++ b/editeng/source/misc/swafopt.cxx
@@ -0,0 +1,163 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: swafopt.cxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+#include <vcl/keycodes.hxx>
+#include <tools/string.hxx>
+
+#include <editeng/swafopt.hxx>
+
+/*------------------------------------------------------------------------
+ Beschreibung:
+------------------------------------------------------------------------*/
+
+SvxSwAutoFmtFlags::SvxSwAutoFmtFlags()
+ : aBulletFont( String::CreateFromAscii(
+ RTL_CONSTASCII_STRINGPARAM( "StarSymbol" )),
+ Size( 0, 14 ) )
+{
+ bReplaceQuote =
+ bAutoCorrect =
+ bCptlSttSntnc =
+ bCptlSttWrd =
+ bChkFontAttr =
+ bChgUserColl =
+ bChgEnumNum =
+ bChgFracionSymbol =
+ bChgOrdinalNumber =
+ bChgToEnEmDash =
+ bChgWeightUnderl =
+ bSetINetAttr =
+ bAFmtDelSpacesAtSttEnd =
+ bAFmtDelSpacesBetweenLines =
+ bAFmtByInpDelSpacesAtSttEnd =
+ bAFmtByInpDelSpacesBetweenLines =
+ bDummy = TRUE;
+
+ bReplaceStyles =
+ bDelEmptyNode =
+ bWithRedlining =
+ bAutoCmpltEndless =
+ bAutoCmpltAppendBlanc =
+ bAutoCmpltShowAsTip = FALSE;
+
+ bSetBorder =
+ bCreateTable =
+ bSetNumRule =
+ bAFmtByInput =
+ bRightMargin =
+ bAutoCompleteWords =
+ bAutoCmpltCollectWords =
+ bAutoCmpltKeepList = TRUE;
+
+ bDummy6 = bDummy7 = bDummy8 =
+ FALSE;
+
+ nRightMargin = 50; // dflt. 50 %
+ nAutoCmpltExpandKey = KEY_RETURN;
+
+ aBulletFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
+ aBulletFont.SetFamily( FAMILY_DONTKNOW );
+ aBulletFont.SetPitch( PITCH_DONTKNOW );
+ aBulletFont.SetWeight( WEIGHT_DONTKNOW );
+ aBulletFont.SetTransparent( TRUE );
+
+ cBullet = 0x2022;
+ cByInputBullet = cBullet;
+ aByInputBulletFont = aBulletFont;
+
+ nAutoCmpltWordLen = 10;
+ nAutoCmpltListLen = 500;
+ pAutoCmpltList = 0;
+ pSmartTagMgr = 0;
+}
+
+
+SvxSwAutoFmtFlags& SvxSwAutoFmtFlags::operator=( const SvxSwAutoFmtFlags& rAFFlags )
+{
+ bAutoCorrect = rAFFlags.bAutoCorrect;
+ bReplaceQuote = rAFFlags.bReplaceQuote;
+ bCptlSttSntnc = rAFFlags.bCptlSttSntnc;
+ bCptlSttWrd = rAFFlags.bCptlSttWrd;
+ bChkFontAttr = rAFFlags.bChkFontAttr;
+
+ bChgUserColl = rAFFlags.bChgUserColl;
+ bChgEnumNum = rAFFlags.bChgEnumNum;
+ bDelEmptyNode = rAFFlags.bDelEmptyNode;
+ bSetNumRule = rAFFlags.bSetNumRule;
+ bAFmtByInput = rAFFlags.bAFmtByInput;
+
+ bChgFracionSymbol = rAFFlags.bChgFracionSymbol;
+ bChgOrdinalNumber = rAFFlags.bChgOrdinalNumber;
+ bChgToEnEmDash = rAFFlags.bChgToEnEmDash;
+ bChgWeightUnderl = rAFFlags.bChgWeightUnderl;
+ bSetINetAttr = rAFFlags.bSetINetAttr;
+ bSetBorder = rAFFlags.bSetBorder;
+ bCreateTable = rAFFlags.bCreateTable;
+ bReplaceStyles = rAFFlags.bReplaceStyles;
+ bAFmtDelSpacesAtSttEnd = rAFFlags.bAFmtDelSpacesAtSttEnd;
+ bAFmtDelSpacesBetweenLines = rAFFlags.bAFmtDelSpacesBetweenLines;
+ bAFmtByInpDelSpacesAtSttEnd = rAFFlags.bAFmtByInpDelSpacesAtSttEnd;
+ bAFmtByInpDelSpacesBetweenLines = rAFFlags.bAFmtByInpDelSpacesBetweenLines;
+
+ bDummy = rAFFlags.bDummy;
+
+ bDummy6 = rAFFlags.bDummy6;
+ bDummy7 = rAFFlags.bDummy7;
+ bDummy8 = rAFFlags.bDummy8;
+
+ bWithRedlining = rAFFlags.bWithRedlining;
+
+ bRightMargin = rAFFlags.bRightMargin;
+ nRightMargin = rAFFlags.nRightMargin;
+
+ cBullet = rAFFlags.cBullet;
+ aBulletFont = rAFFlags.aBulletFont;
+
+ cByInputBullet = rAFFlags.cByInputBullet;
+ aByInputBulletFont = rAFFlags.aByInputBulletFont;
+
+ bAutoCompleteWords = rAFFlags.bAutoCompleteWords;
+ bAutoCmpltCollectWords = rAFFlags.bAutoCmpltCollectWords;
+ bAutoCmpltKeepList = rAFFlags.bAutoCmpltKeepList;
+ bAutoCmpltEndless = rAFFlags.bAutoCmpltEndless;
+ bAutoCmpltAppendBlanc = rAFFlags.bAutoCmpltAppendBlanc;
+ bAutoCmpltShowAsTip = rAFFlags.bAutoCmpltShowAsTip;
+ pAutoCmpltList = rAFFlags.pAutoCmpltList;
+ pSmartTagMgr = rAFFlags.pSmartTagMgr;
+ nAutoCmpltExpandKey = rAFFlags.nAutoCmpltExpandKey;
+
+ nAutoCmpltWordLen = rAFFlags.nAutoCmpltWordLen;
+ nAutoCmpltListLen = rAFFlags.nAutoCmpltListLen;
+
+ return *this;
+}
+
diff --git a/editeng/source/misc/txtrange.cxx b/editeng/source/misc/txtrange.cxx
new file mode 100644
index 0000000000..0c7f9dc7aa
--- /dev/null
+++ b/editeng/source/misc/txtrange.cxx
@@ -0,0 +1,722 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: txtrange.cxx,v $
+ * $Revision: 1.15 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <editeng/txtrange.hxx>
+#include <math.h>
+#include <tools/poly.hxx>
+#include <tools/debug.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+/*************************************************************************
+|*
+|* TextRanger::TextRanger()
+|*
+|* Beschreibung
+|* Ersterstellung 20.01.97
+|* Letzte Aenderung 20.01.97 AMA
+|*
+*************************************************************************/
+
+#ifdef WIN
+#pragma optimize ( "", off )
+#endif
+
+TextRanger::TextRanger( const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DPolyPolygon* pLinePolyPolygon,
+ USHORT nCacheSz, USHORT nLft, USHORT nRght, BOOL bSimpl, BOOL bInnr,
+ BOOL bVert ) :
+ pBound( NULL ),
+ nCacheSize( nCacheSz ),
+ nCacheIdx( 0 ),
+ nRight( nRght ),
+ nLeft( nLft ),
+ nUpper( 0 ),
+ nLower( 0 ),
+ nPointCount( 0 ),
+ bSimple( bSimpl ),
+ bInner( bInnr ),
+ bVertical( bVert )
+{
+#ifdef DBG_UTIL
+ bFlag3 = bFlag4 = bFlag5 = bFlag6 = bFlag7 = FALSE;
+#endif
+ pRangeArr = new Range[ nCacheSize ];
+ pCache = new SvLongsPtr[ nCacheSize ];
+ memset( pRangeArr, 0, nCacheSize * sizeof( Range ) );
+ memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) );
+ sal_uInt32 nCount(rPolyPolygon.count());
+ mpPolyPolygon = new PolyPolygon( (sal_uInt16)nCount );
+
+ for(sal_uInt32 i(0L); i < nCount; i++)
+ {
+ const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(i).getDefaultAdaptiveSubdivision());
+ nPointCount += aCandidate.count();
+ mpPolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
+ }
+
+ if( pLinePolyPolygon )
+ {
+ nCount = pLinePolyPolygon->count();
+ mpLinePolyPolygon = new PolyPolygon();
+
+ for(sal_uInt32 i(0L); i < nCount; i++)
+ {
+ const basegfx::B2DPolygon aCandidate(pLinePolyPolygon->getB2DPolygon(i).getDefaultAdaptiveSubdivision());
+ nPointCount += aCandidate.count();
+ mpLinePolyPolygon->Insert( Polygon(aCandidate), (sal_uInt16)i );
+ }
+ }
+ else
+ mpLinePolyPolygon = NULL;
+}
+
+#ifdef WIN
+#pragma optimize ( "", on )
+#endif
+
+/*************************************************************************
+|*
+|* TextRanger::~TextRanger()
+|*
+|* Beschreibung
+|* Ersterstellung 20.01.97
+|* Letzte Aenderung 20.01.97 AMA
+|*
+*************************************************************************/
+
+TextRanger::~TextRanger()
+{
+ for( USHORT i = 0; i < nCacheSize; ++i )
+ delete pCache[i];
+ delete[] pCache;
+ delete[] pRangeArr;
+ delete mpPolyPolygon;
+ delete mpLinePolyPolygon;
+}
+
+/*-----------------17.11.00 09:49-------------------
+ * TextRanger::SetVertical(..)
+ * If there's is a change in the writing direction,
+ * the cache has to be cleared.
+ * --------------------------------------------------*/
+
+void TextRanger::SetVertical( BOOL bNew )
+{
+ if( IsVertical() != bNew )
+ {
+ bVertical = bNew;
+ for( USHORT i = 0; i < nCacheSize; ++i )
+ delete pCache[i];
+ memset( pRangeArr, 0, nCacheSize * sizeof( Range ) );
+ memset( pCache, 0, nCacheSize * sizeof( SvLongsPtr ) );
+ }
+}
+
+/*************************************************************************
+|*
+|* SvxBoundArgs
+|*
+|* Beschreibung
+|* Ersterstellung 20.01.97
+|* Letzte Aenderung 20.01.97 AMA
+|*
+*************************************************************************/
+
+class SvxBoundArgs
+{
+ SvBools aBoolArr;
+ SvLongs *pLongArr;
+ TextRanger *pTextRanger;
+ long nMin;
+ long nMax;
+ long nTop;
+ long nBottom;
+ long nUpDiff;
+ long nLowDiff;
+ long nUpper;
+ long nLower;
+ long nStart;
+ long nEnd;
+ USHORT nCut;
+ USHORT nLast;
+ USHORT nNext;
+ BYTE nAct;
+ BYTE nFirst;
+ BOOL bClosed : 1;
+ BOOL bInner : 1;
+ BOOL bMultiple : 1;
+ BOOL bConcat : 1;
+ BOOL bRotate : 1;
+ void NoteRange( BOOL bToggle );
+ long Cut( long nY, const Point& rPt1, const Point& rPt2 );
+ void Add();
+ void _NoteFarPoint( long nPx, long nPyDiff, long nDiff );
+ void NoteFarPoint( long nPx, long nPyDiff, long nDiff )
+ { if( nDiff ) _NoteFarPoint( nPx, nPyDiff, nDiff ); }
+ long CalcMax( const Point& rPt1, const Point& rPt2, long nRange, long nFar );
+ void CheckCut( const Point& rLst, const Point& rNxt );
+ inline long A( const Point& rP ) const { return bRotate ? rP.Y() : rP.X(); }
+ inline long B( const Point& rP ) const { return bRotate ? rP.X() : rP.Y(); }
+public:
+ SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong, const Range& rRange );
+ void NotePoint( const long nA ) { NoteMargin( nA - nStart, nA + nEnd ); }
+ void NoteMargin( const long nL, const long nR )
+ { if( nMin > nL ) nMin = nL; if( nMax < nR ) nMax = nR; }
+ USHORT Area( const Point& rPt );
+ void NoteUpLow( long nA, const BYTE nArea );
+ void Calc( const PolyPolygon& rPoly );
+ void Concat( const PolyPolygon* pPoly );
+ // inlines
+ void NoteLast() { if( bMultiple ) NoteRange( nAct == nFirst ); }
+ void SetClosed( const BOOL bNew ){ bClosed = bNew; }
+ BOOL IsClosed() const { return bClosed; }
+ void SetConcat( const BOOL bNew ){ bConcat = bNew; }
+ BOOL IsConcat() const { return bConcat; }
+ BYTE GetAct() const { return nAct; }
+};
+
+SvxBoundArgs::SvxBoundArgs( TextRanger* pRanger, SvLongs *pLong,
+ const Range& rRange )
+ : aBoolArr( 4, 4 ), pLongArr( pLong ), pTextRanger( pRanger ),
+ nTop( rRange.Min() ), nBottom( rRange.Max() ),
+ bInner( pRanger->IsInner() ), bMultiple( bInner || !pRanger->IsSimple() ),
+ bConcat( FALSE ), bRotate( pRanger->IsVertical() )
+{
+ if( bRotate )
+ {
+ nStart = pRanger->GetUpper();
+ nEnd = pRanger->GetLower();
+ nLowDiff = pRanger->GetLeft();
+ nUpDiff = pRanger->GetRight();
+ }
+ else
+ {
+ nStart = pRanger->GetLeft();
+ nEnd = pRanger->GetRight();
+ nLowDiff = pRanger->GetUpper();
+ nUpDiff = pRanger->GetLower();
+ }
+ nUpper = nTop - nUpDiff;
+ nLower = nBottom + nLowDiff;
+ pLongArr->Remove( 0, pLongArr->Count() );
+}
+
+long SvxBoundArgs::CalcMax( const Point& rPt1, const Point& rPt2,
+ long nRange, long nFarRange )
+{
+ double nDa = Cut( nRange, rPt1, rPt2 ) - Cut( nFarRange, rPt1, rPt2 );
+ double nB;
+ if( nDa < 0 )
+ {
+ nDa = -nDa;
+ nB = nEnd;
+ }
+ else
+ nB = nStart;
+ nB *= nB;
+ nB += nDa * nDa;
+ nB = nRange + nDa * ( nFarRange - nRange ) / sqrt( nB );
+
+ BOOL bNote;
+ if( nB < B(rPt2) )
+ bNote = nB > B(rPt1);
+ else
+ bNote = nB < B(rPt1);
+ if( bNote )
+ return( long( nB ) );
+ return 0;
+}
+
+void SvxBoundArgs::CheckCut( const Point& rLst, const Point& rNxt )
+{
+ if( nCut & 1 )
+ NotePoint( Cut( nBottom, rLst, rNxt ) );
+ if( nCut & 2 )
+ NotePoint( Cut( nTop, rLst, rNxt ) );
+ if( rLst.X() != rNxt.X() && rLst.Y() != rNxt.Y() )
+ {
+ long nYps;
+ if( nLowDiff && ( ( nCut & 1 ) || nLast == 1 || nNext == 1 ) )
+ {
+ nYps = CalcMax( rLst, rNxt, nBottom, nLower );
+ if( nYps )
+ _NoteFarPoint( Cut( nYps, rLst, rNxt ), nLower-nYps, nLowDiff );
+ }
+ if( nUpDiff && ( ( nCut & 2 ) || nLast == 2 || nNext == 2 ) )
+ {
+ nYps = CalcMax( rLst, rNxt, nTop, nUpper );
+ if( nYps )
+ _NoteFarPoint( Cut( nYps, rLst, rNxt ), nYps-nUpper, nUpDiff );
+ }
+ }
+}
+
+void SvxBoundArgs::_NoteFarPoint( long nPa, long nPbDiff, long nDiff )
+{
+ long nTmpA;
+ double nQuot = 2 * nDiff - nPbDiff;
+ nQuot *= nPbDiff;
+ nQuot = sqrt( nQuot );
+ nQuot /= nDiff;
+ nTmpA = nPa - long( nStart * nQuot );
+ nPbDiff = nPa + long( nEnd * nQuot );
+ NoteMargin( nTmpA, nPbDiff );
+}
+
+void SvxBoundArgs::NoteRange( BOOL bToggle )
+{
+ DBG_ASSERT( nMax >= nMin || bInner, "NoteRange: Min > Max?");
+ if( nMax < nMin )
+ return;
+ if( !bClosed )
+ bToggle = FALSE;
+ USHORT nIdx = 0;
+ USHORT nCount = pLongArr->Count();
+ DBG_ASSERT( nCount == 2 * aBoolArr.Count(), "NoteRange: Incompatible Sizes" );
+ while( nIdx < nCount && (*pLongArr)[ nIdx ] < nMin )
+ ++nIdx;
+ BOOL bOdd = nIdx % 2 ? TRUE : FALSE;
+ // Kein Ueberlappung mit vorhandenen Intervallen?
+ if( nIdx == nCount || ( !bOdd && nMax < (*pLongArr)[ nIdx ] ) )
+ { // Dann wird ein neues eingefuegt ...
+ pLongArr->Insert( nMin, nIdx );
+ pLongArr->Insert( nMax, nIdx + 1 );
+ aBoolArr.Insert( bToggle, nIdx / 2 );
+ }
+ else
+ { // ein vorhandes Intervall erweitern ...
+ USHORT nMaxIdx = nIdx;
+ // Wenn wir auf einer linken Intervallgrenze gelandet sind, muss diese
+ // auf nMin gesenkt werden.
+ if( bOdd )
+ --nIdx;
+ else
+ (*pLongArr)[ nIdx ] = nMin;
+ while( nMaxIdx < nCount && (*pLongArr)[ nMaxIdx ] < nMax )
+ ++nMaxIdx;
+ DBG_ASSERT( nMaxIdx > nIdx || nMin == nMax, "NoteRange: Funny Situation." );
+ if( nMaxIdx )
+ --nMaxIdx;
+ if( nMaxIdx < nIdx )
+ nMaxIdx = nIdx;
+ // Wenn wir auf einer rechten Intervallgrenze landen, muss diese
+ // auf nMax angehoben werden.
+ if( nMaxIdx % 2 )
+ (*pLongArr)[ nMaxIdx-- ] = nMax;
+ // Jetzt werden eventuell noch Intervalle verschmolzen
+ USHORT nDiff = nMaxIdx - nIdx;
+ nMaxIdx = nIdx / 2; // Ab hier ist nMaxIdx der Index im BoolArray.
+ if( nDiff )
+ {
+ (*pLongArr).Remove( nIdx + 1, nDiff );
+ nDiff /= 2;
+ USHORT nStop = nMaxIdx + nDiff;
+ for( USHORT i = nMaxIdx; i < nStop; ++i )
+ bToggle ^= aBoolArr[ i ];
+ aBoolArr.Remove( nMaxIdx, nDiff );
+ }
+ DBG_ASSERT( nMaxIdx < aBoolArr.Count(), "NoteRange: Too much deleted" );
+ aBoolArr[ nMaxIdx ] ^= bToggle;
+ }
+}
+
+void SvxBoundArgs::Calc( const PolyPolygon& rPoly )
+{
+ USHORT nCount;
+ nAct = 0;
+ for( USHORT i = 0; i < rPoly.Count(); ++i )
+ {
+ const Polygon& rPol = rPoly[ i ];
+ nCount = rPol.GetSize();
+ if( nCount )
+ {
+ const Point& rNull = rPol[ 0 ];
+ SetClosed( IsConcat() || ( rNull == rPol[ nCount - 1 ] ) );
+ nLast = Area( rNull );
+ if( nLast & 12 )
+ {
+ nFirst = 3;
+ if( bMultiple )
+ nAct = 0;
+ }
+ else
+ {
+ // Der erste Punkt des Polygons liegt innerhalb der Zeile.
+ if( nLast )
+ {
+ if( bMultiple || !nAct )
+ {
+ nMin = USHRT_MAX;
+ nMax = 0;
+ }
+ if( nLast & 1 )
+ NoteFarPoint( A(rNull), nLower - B(rNull), nLowDiff );
+ else
+ NoteFarPoint( A(rNull), B(rNull) - nUpper, nUpDiff );
+ }
+ else
+ {
+ if( bMultiple || !nAct )
+ {
+ nMin = A(rNull);
+ nMax = nMin + nEnd;
+ nMin -= nStart;
+ }
+ else
+ NotePoint( A(rNull) );
+ }
+ nFirst = 0; // In welcher Richtung wird die Zeile verlassen?
+ nAct = 3; // Wir sind z.Z. innerhalb der Zeile.
+ }
+ if( nCount > 1 )
+ {
+ USHORT nIdx = 1;
+ while( TRUE )
+ {
+ const Point& rLast = rPol[ nIdx - 1 ];
+ if( nIdx == nCount )
+ nIdx = 0;
+ const Point& rNext = rPol[ nIdx ];
+ nNext = Area( rNext );
+ nCut = nNext ^ nLast;
+ USHORT nOldAct = nAct;
+ if( nAct )
+ CheckCut( rLast, rNext );
+ if( nCut & 4 )
+ {
+ NoteUpLow( Cut( nLower, rLast, rNext ), 2 );
+ if( nAct && nAct != nOldAct )
+ {
+ nOldAct = nAct;
+ CheckCut( rLast, rNext );
+ }
+ }
+ if( nCut & 8 )
+ {
+ NoteUpLow( Cut( nUpper, rLast, rNext ), 1 );
+ if( nAct && nAct != nOldAct )
+ CheckCut( rLast, rNext );
+ }
+ if( !nIdx )
+ {
+ if( !( nNext & 12 ) )
+ NoteLast();
+ break;
+ }
+ if( !( nNext & 12 ) )
+ {
+ if( !nNext )
+ NotePoint( A(rNext) );
+ else if( nNext & 1 )
+ NoteFarPoint( A(rNext), nLower-B(rNext), nLowDiff );
+ else
+ NoteFarPoint( A(rNext), B(rNext)-nUpper, nUpDiff );
+ }
+ nLast = nNext;
+ if( ++nIdx == nCount && !IsClosed() )
+ {
+ if( !( nNext & 12 ) )
+ NoteLast();
+ break;
+ }
+ }
+ }
+ if( bMultiple && IsConcat() )
+ {
+ Add();
+ nAct = 0;
+ }
+ }
+ }
+ if( !bMultiple )
+ {
+ DBG_ASSERT( pLongArr->Count() == 0, "I said: Simple!" );
+ if( nAct )
+ {
+ if( bInner )
+ {
+ long nTmpMin, nTmpMax;
+ {
+ nTmpMin = nMin + 2 * nStart;
+ nTmpMax = nMax - 2 * nEnd;
+ if( nTmpMin <= nTmpMax )
+ {
+ pLongArr->Insert( nTmpMin, 0 );
+ pLongArr->Insert( nTmpMax, 1 );
+ }
+ }
+ }
+ else
+ {
+ pLongArr->Insert( nMin, 0 );
+ pLongArr->Insert( nMax, 1 );
+ }
+ }
+ }
+ else if( !IsConcat() )
+ Add();
+}
+
+void SvxBoundArgs::Add()
+{
+ USHORT nLongIdx = 1;
+ USHORT nCount = aBoolArr.Count();
+ if( nCount && ( !bInner || !pTextRanger->IsSimple() ) )
+ {
+ BOOL bDelete = aBoolArr[ 0 ];
+ if( bInner )
+ bDelete = !bDelete;
+ for( USHORT nBoolIdx = 1; nBoolIdx < nCount; ++nBoolIdx )
+ {
+ if( bDelete )
+ {
+ USHORT next = 2;
+ while( nBoolIdx < nCount && !aBoolArr[ nBoolIdx++ ] &&
+ (!bInner || nBoolIdx < nCount ) )
+ next += 2;
+ pLongArr->Remove( nLongIdx, next );
+ next /= 2;
+ nBoolIdx = nBoolIdx - next;
+ nCount = nCount - next;
+ aBoolArr.Remove( nBoolIdx, next );
+ if( nBoolIdx )
+ aBoolArr[ nBoolIdx - 1 ] = FALSE;
+#if OSL_DEBUG_LEVEL > 1
+ else
+ ++next;
+#endif
+ }
+ bDelete = nBoolIdx < nCount && aBoolArr[ nBoolIdx ];
+ nLongIdx += 2;
+ DBG_ASSERT( nLongIdx == 2*nBoolIdx+1, "BoundArgs: Array-Idx Confusion" );
+ DBG_ASSERT( aBoolArr.Count()*2 == pLongArr->Count(),
+ "BoundArgs: Array-Count: Confusion" );
+ }
+ }
+ if( 0 != ( nCount = pLongArr->Count() ) )
+ {
+ if( bInner )
+ {
+ pLongArr->Remove( 0, 1 );
+ pLongArr->Remove( pLongArr->Count() - 1, 1 );
+
+ // Hier wird die Zeile beim "einfachen" Konturumfluss im Innern
+ // in ein grosses Rechteck zusammengefasst.
+ // Zur Zeit (April 1999) wertet die EditEngine nur das erste Rechteck
+ // aus, falls sie eines Tages in der Lage ist, eine Zeile in mehreren
+ // Teilen auszugeben, kann es sinnvoll sein, die folgenden Zeilen
+ // zu loeschen.
+ if( pTextRanger->IsSimple() && pLongArr->Count() > 2 )
+ pLongArr->Remove( 1, pLongArr->Count() - 2 );
+
+ }
+ }
+}
+
+void SvxBoundArgs::Concat( const PolyPolygon* pPoly )
+{
+ SetConcat( TRUE );
+ DBG_ASSERT( pPoly, "Nothing to do?" );
+ SvLongs *pOld = pLongArr;
+ pLongArr = new SvLongs( 2, 8 );
+ aBoolArr.Remove( 0, aBoolArr.Count() );
+ bInner = FALSE;
+ Calc( *pPoly );
+ USHORT nCount = pLongArr->Count();
+ USHORT nIdx = 0;
+ USHORT i = 0;
+ BOOL bSubtract = pTextRanger->IsInner();
+ while( i < nCount )
+ {
+ USHORT nOldCount = pOld->Count();
+ if( nIdx == nOldCount )
+ { // Am Ende des alten Arrays angelangt...
+ if( !bSubtract )
+ pOld->Insert( pLongArr, nIdx, i, USHRT_MAX );
+ break;
+ }
+ long nLeft = (*pLongArr)[ i++ ];
+ long nRight = (*pLongArr)[ i++ ];
+ USHORT nLeftPos = nIdx + 1;
+ while( nLeftPos < nOldCount && nLeft > (*pOld)[ nLeftPos ] )
+ nLeftPos += 2;
+ if( nLeftPos >= nOldCount )
+ { // Das aktuelle Intervall gehoert ans Ende des alten Arrays...
+ if( !bSubtract )
+ pOld->Insert( pLongArr, nOldCount, i - 2, USHRT_MAX );
+ break;
+ }
+ USHORT nRightPos = nLeftPos - 1;
+ while( nRightPos < nOldCount && nRight >= (*pOld)[ nRightPos ] )
+ nRightPos += 2;
+ if( nRightPos < nLeftPos )
+ { // Das aktuelle Intervall gehoert zwischen zwei alte Intervalle
+ if( !bSubtract )
+ pOld->Insert( pLongArr, nRightPos, i - 2, i );
+ nIdx = nRightPos + 2;
+ }
+ else if( bSubtract ) // Subtrahieren ggf. Trennen
+ {
+ long nOld;
+ if( nLeft > ( nOld = (*pOld)[ nLeftPos - 1 ] ) )
+ { // Jetzt spalten wir den linken Teil ab...
+ if( nLeft - 1 > nOld )
+ {
+ pOld->Insert( nOld, nLeftPos - 1 );
+ pOld->Insert( nLeft - 1, nLeftPos );
+ nLeftPos += 2;
+ nRightPos += 2;
+ }
+ }
+ if( nRightPos - nLeftPos > 1 )
+ pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 );
+ if( ++nRight >= ( nOld = (*pOld)[ nLeftPos ] ) )
+ pOld->Remove( nLeftPos - 1, 2 );
+ else
+ (*pOld)[ nLeftPos - 1 ] = nRight;
+ }
+ else // Verschmelzen
+ {
+ if( nLeft < (*pOld)[ nLeftPos - 1 ] )
+ (*pOld)[ nLeftPos - 1 ] = nLeft;
+ if( nRight > (*pOld)[ nRightPos - 1 ] )
+ (*pOld)[ nRightPos - 1 ] = nRight;
+ if( nRightPos - nLeftPos > 1 )
+ pOld->Remove( nLeftPos, nRightPos - nLeftPos - 1 );
+
+ }
+ nIdx = nLeftPos - 1;
+ }
+ delete pLongArr;
+}
+
+/*************************************************************************
+ * SvxBoundArgs::Area ermittelt den Bereich, in dem sich der Punkt befindet
+ * 0 = innerhalb der Zeile
+ * 1 = unterhalb, aber innerhalb der oberen Randes
+ * 2 = oberhalb, aber innerhalb der unteren Randes
+ * 5 = unterhalb des oberen Randes
+ *10 = oberhalb des unteren Randes
+ *************************************************************************/
+
+USHORT SvxBoundArgs::Area( const Point& rPt )
+{
+ long nB = B( rPt );
+ if( nB >= nBottom )
+ {
+ if( nB >= nLower )
+ return 5;
+ return 1;
+ }
+ if( nB <= nTop )
+ {
+ if( nB <= nUpper )
+ return 10;
+ return 2;
+ }
+ return 0;
+}
+
+/*************************************************************************
+ * lcl_Cut berechnet die X-Koordinate der Strecke (Pt1-Pt2) auf der
+ * Y-Koordinate nY.
+ * Vorausgesetzt wird, dass einer der Punkte oberhalb und der andere
+ * unterhalb der Y-Koordinate liegt.
+ *************************************************************************/
+
+long SvxBoundArgs::Cut( long nB, const Point& rPt1, const Point& rPt2 )
+{
+ if( pTextRanger->IsVertical() )
+ {
+ double nQuot = nB - rPt1.X();
+ nQuot /= ( rPt2.X() - rPt1.X() );
+ nQuot *= ( rPt2.Y() - rPt1.Y() );
+ return long( rPt1.Y() + nQuot );
+ }
+ double nQuot = nB - rPt1.Y();
+ nQuot /= ( rPt2.Y() - rPt1.Y() );
+ nQuot *= ( rPt2.X() - rPt1.X() );
+ return long( rPt1.X() + nQuot );
+}
+
+void SvxBoundArgs::NoteUpLow( long nA, const BYTE nArea )
+{
+ if( nAct )
+ {
+ NoteMargin( nA, nA );
+ if( bMultiple )
+ {
+ NoteRange( nArea != nAct );
+ nAct = 0;
+ }
+ if( !nFirst )
+ nFirst = nArea;
+ }
+ else
+ {
+ nAct = nArea;
+ nMin = nA;
+ nMax = nA;
+ }
+}
+
+SvLongsPtr TextRanger::GetTextRanges( const Range& rRange )
+{
+ DBG_ASSERT( rRange.Min() || rRange.Max(), "Zero-Range not allowed, Bye Bye" );
+ USHORT nIndex = 0;
+ while( nIndex < nCacheSize && rRange != pRangeArr[ nIndex ] )
+ ++nIndex;
+ if( nIndex >= nCacheSize )
+ {
+ ++nCacheIdx;
+ nCacheIdx %= nCacheSize;
+ pRangeArr[ nCacheIdx ] = rRange;
+ if( !pCache[ nCacheIdx ] )
+ pCache[ nCacheIdx ] = new SvLongs( 2, 8 );
+ nIndex = nCacheIdx;
+ SvxBoundArgs aArg( this, pCache[ nCacheIdx ], rRange );
+ aArg.Calc( *mpPolyPolygon );
+ if( mpLinePolyPolygon )
+ aArg.Concat( mpLinePolyPolygon );
+ }
+ return pCache[ nIndex ];
+}
+
+const Rectangle& TextRanger::_GetBoundRect()
+{
+ DBG_ASSERT( 0 == pBound, "Don't call twice." );
+ pBound = new Rectangle( mpPolyPolygon->GetBoundRect() );
+ return *pBound;
+}
+
+
diff --git a/editeng/source/misc/unolingu.cxx b/editeng/source/misc/unolingu.cxx
new file mode 100644
index 0000000000..f356c4be73
--- /dev/null
+++ b/editeng/source/misc/unolingu.cxx
@@ -0,0 +1,1377 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: unolingu.cxx,v $
+ * $Revision: 1.39 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+#include <map>
+#include <set>
+#include <vector>
+#include <slist>
+#include <memory>
+#include <editeng/unolingu.hxx>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <rtl/logfile.hxx>
+#include <unotools/pathoptions.hxx>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <com/sun/star/linguistic2/XAvailableLocales.hpp>
+#include <com/sun/star/ucb/XAnyCompareFactory.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
+#include <com/sun/star/ucb/NumberedSortingInfo.hpp>
+#include <com/sun/star/ucb/XContentAccess.hpp>
+#include <com/sun/star/sdbc/XResultSet.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/implbase1.hxx> // helper for implementations
+#include <i18npool/mslangid.hxx>
+#include <unotools/lingucfg.hxx>
+#include <unotools/ucbhelper.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+#include <ucbhelper/content.hxx>
+#include <comphelper/processfactory.hxx>
+#include <vcl/msgbox.hxx>
+#include <tools/shl.hxx>
+#include <linguistic/misc.hxx>
+#include <editeng/eerdll.hxx>
+#include <editeng/editrids.hrc>
+
+using namespace ::rtl;
+using namespace ::comphelper;
+using namespace ::linguistic;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::linguistic2;
+
+#define CSS com::sun::star
+
+///////////////////////////////////////////////////////////////////////////
+
+
+static uno::Reference< XLinguServiceManager > GetLngSvcMgr_Impl()
+{
+ uno::Reference< XLinguServiceManager > xRes;
+ uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory();
+ if (xMgr.is())
+ {
+ xRes = uno::Reference< XLinguServiceManager > ( xMgr->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM(
+ "com.sun.star.linguistic2.LinguServiceManager" ) ) ), UNO_QUERY ) ;
+ }
+ return xRes;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+BOOL lcl_FindEntry( const OUString &rEntry, const Sequence< OUString > &rCfgSvcs )
+{
+ INT32 nRes = -1;
+ INT32 nEntries = rCfgSvcs.getLength();
+ const OUString *pEntry = rCfgSvcs.getConstArray();
+ for (INT32 i = 0; i < nEntries && nRes == -1; ++i)
+ {
+ if (rEntry == pEntry[i])
+ nRes = i;
+ }
+ return nRes != -1;
+}
+
+
+Sequence< OUString > lcl_RemoveMissingEntries(
+ const Sequence< OUString > &rCfgSvcs,
+ const Sequence< OUString > &rAvailSvcs )
+{
+ Sequence< OUString > aRes( rCfgSvcs.getLength() );
+ OUString *pRes = aRes.getArray();
+ INT32 nCnt = 0;
+
+ INT32 nEntries = rCfgSvcs.getLength();
+ const OUString *pEntry = rCfgSvcs.getConstArray();
+ for (INT32 i = 0; i < nEntries; ++i)
+ {
+ if (pEntry[i].getLength() && lcl_FindEntry( pEntry[i], rAvailSvcs ))
+ pRes[ nCnt++ ] = pEntry[i];
+ }
+
+ aRes.realloc( nCnt );
+ return aRes;
+}
+
+
+Sequence< OUString > lcl_GetLastFoundSvcs(
+ SvtLinguConfig &rCfg,
+ const OUString &rLastFoundList ,
+ const Locale &rAvailLocale )
+{
+ Sequence< OUString > aRes;
+
+ OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
+ SvxLocaleToLanguage( rAvailLocale ) ) );
+
+ Sequence< OUString > aNodeNames( rCfg.GetNodeNames(rLastFoundList) );
+ BOOL bFound = lcl_FindEntry( aCfgLocaleStr, aNodeNames);
+
+ if (bFound)
+ {
+ Sequence< OUString > aNames(1);
+ OUString &rNodeName = aNames.getArray()[0];
+ rNodeName = rLastFoundList;
+ rNodeName += OUString::valueOf( (sal_Unicode)'/' );
+ rNodeName += aCfgLocaleStr;
+ Sequence< Any > aValues( rCfg.GetProperties( aNames ) );
+#if OSL_DEBUG_LEVEL > 1
+ const Any *pValue;
+ pValue = aValues.getConstArray();
+#endif
+ if (aValues.getLength())
+ {
+ DBG_ASSERT( aValues.getLength() == 1, "unexpected length of sequence" );
+ Sequence< OUString > aSvcImplNames;
+ if (aValues.getConstArray()[0] >>= aSvcImplNames)
+ aRes = aSvcImplNames;
+ else
+ {
+ DBG_ERROR( "type mismatch" );
+ }
+ }
+ }
+
+ return aRes;
+}
+
+
+Sequence< OUString > lcl_GetNewEntries(
+ const Sequence< OUString > &rLastFoundSvcs,
+ const Sequence< OUString > &rAvailSvcs )
+{
+ INT32 nLen = rAvailSvcs.getLength();
+ Sequence< OUString > aRes( nLen );
+ OUString *pRes = aRes.getArray();
+ INT32 nCnt = 0;
+
+ const OUString *pEntry = rAvailSvcs.getConstArray();
+ for (INT32 i = 0; i < nLen; ++i)
+ {
+ if (pEntry[i].getLength() && !lcl_FindEntry( pEntry[i], rLastFoundSvcs ))
+ pRes[ nCnt++ ] = pEntry[i];
+ }
+
+ aRes.realloc( nCnt );
+ return aRes;
+}
+
+
+Sequence< OUString > lcl_MergeSeq(
+ const Sequence< OUString > &rCfgSvcs,
+ const Sequence< OUString > &rNewSvcs )
+{
+ Sequence< OUString > aRes( rCfgSvcs.getLength() + rNewSvcs.getLength() );
+ OUString *pRes = aRes.getArray();
+ INT32 nCnt = 0;
+
+ for (INT32 k = 0; k < 2; ++k)
+ {
+ // add previously configuerd service first and append
+ // new found services at the end
+ const Sequence< OUString > &rSeq = k == 0 ? rCfgSvcs : rNewSvcs;
+
+ INT32 nLen = rSeq.getLength();
+ const OUString *pEntry = rSeq.getConstArray();
+ for (INT32 i = 0; i < nLen; ++i)
+ {
+ if (pEntry[i].getLength() && !lcl_FindEntry( pEntry[i], aRes ))
+ pRes[ nCnt++ ] = pEntry[i];
+ }
+ }
+
+ aRes.realloc( nCnt );
+ return aRes;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+// static member initialization
+INT16 SvxLinguConfigUpdate::nNeedUpdating = -1;
+INT32 SvxLinguConfigUpdate::nCurrentDataFilesChangedCheckValue = -1;
+
+void SvxLinguConfigUpdate::UpdateAll( sal_Bool bForceCheck )
+{
+ RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll" );
+
+ if (IsNeedUpdateAll( bForceCheck ))
+ {
+ typedef OUString OUstring_t;
+ typedef Sequence< OUString > Sequence_OUString_t;
+ typedef std::vector< OUstring_t > OUString_vector_t;
+ typedef std::set< OUstring_t > OUString_set_t;
+ std::vector< OUString_vector_t > aVector;
+ typedef std::map< OUstring_t, Sequence_OUString_t > list_entry_map_t;
+
+ RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll - updating..." );
+
+ DBG_ASSERT( nNeedUpdating == 1, "SvxLinguConfigUpdate::UpdateAll already updated!" );
+
+ uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
+ DBG_ASSERT( xLngSvcMgr.is(), "service manager missing");
+ if (!xLngSvcMgr.is())
+ return;
+
+ SvtLinguConfig aCfg;
+
+ const int nNumServices = 4;
+ const sal_Char * apServices[nNumServices] = { SN_SPELLCHECKER, SN_GRAMMARCHECKER, SN_HYPHENATOR, SN_THESAURUS };
+ const sal_Char * apCurLists[nNumServices] = { "ServiceManager/SpellCheckerList", "ServiceManager/GrammarCheckerList", "ServiceManager/HyphenatorList", "ServiceManager/ThesaurusList" };
+ const sal_Char * apLastFoundLists[nNumServices] = { "ServiceManager/LastFoundSpellCheckers", "ServiceManager/LastFoundGrammarCheckers", "ServiceManager/LastFoundHyphenators", "ServiceManager/LastFoundThesauri" };
+
+ // usage of indices as above: 0 = spell checker, 1 = grammar checker, 2 = hyphenator, 3 = thesaurus
+ std::vector< list_entry_map_t > aLastFoundSvcs(nNumServices);
+ std::vector< list_entry_map_t > aCurSvcs(nNumServices);
+
+ for (int k = 0; k < nNumServices; ++k)
+ {
+ OUString aService( A2OU( apServices[k] ) );
+ OUString aActiveList( A2OU( apCurLists[k] ) );
+ OUString aLastFoundList( A2OU( apLastFoundLists[k] ) );
+ INT32 i;
+
+ //
+ // remove configured but not available language/services entries
+ //
+ Sequence< OUString > aNodeNames( aCfg.GetNodeNames( aActiveList ) ); // list of configured locales
+ INT32 nNodeNames = aNodeNames.getLength();
+ const OUString *pNodeName = aNodeNames.getConstArray();
+ for (i = 0; i < nNodeNames; ++i)
+ {
+ Locale aLocale( SvxCreateLocale( MsLangId::convertIsoStringToLanguage(pNodeName[i]) ) );
+ Sequence< OUString > aCfgSvcs(
+ xLngSvcMgr->getConfiguredServices( aService, aLocale ));
+ Sequence< OUString > aAvailSvcs(
+ xLngSvcMgr->getAvailableServices( aService, aLocale ));
+#if OSL_DEBUG_LEVEL > 1
+ const OUString * pCfgSvcs = aCfgSvcs.getConstArray();;
+ const OUString * pAvailSvcs = aAvailSvcs.getConstArray();;
+ (void) pCfgSvcs;
+ (void) pAvailSvcs;
+#endif
+ aCfgSvcs = lcl_RemoveMissingEntries( aCfgSvcs, aAvailSvcs );
+
+ aCurSvcs[k][ pNodeName[i] ] = aCfgSvcs;
+ }
+
+ //
+ // add new available language/servcice entries
+ //
+ uno::Reference< XAvailableLocales > xAvail( xLngSvcMgr, UNO_QUERY );
+ Sequence< Locale > aAvailLocales( xAvail->getAvailableLocales(aService) );
+ INT32 nAvailLocales = aAvailLocales.getLength();
+ const Locale *pAvailLocale = aAvailLocales.getConstArray();
+ for (i = 0; i < nAvailLocales; ++i)
+ {
+ Sequence< OUString > aAvailSvcs(
+ xLngSvcMgr->getAvailableServices( aService, pAvailLocale[i] ));
+ Sequence< OUString > aLastSvcs(
+ lcl_GetLastFoundSvcs( aCfg, aLastFoundList , pAvailLocale[i] ));
+ Sequence< OUString > aNewSvcs =
+ lcl_GetNewEntries( aLastSvcs, aAvailSvcs );
+#if OSL_DEBUG_LEVEL > 1
+ const OUString * pAvailSvcs = aAvailSvcs.getConstArray();
+ const OUString * pLastSvcs = aLastSvcs.getConstArray();
+ const OUString * pNewSvcs = aNewSvcs.getConstArray();
+ (void) pAvailSvcs;
+ (void) pLastSvcs;
+ (void) pNewSvcs;
+#endif
+
+ OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
+ SvxLocaleToLanguage( pAvailLocale[i] ) ) );
+ Sequence< OUString > aCfgSvcs( aCurSvcs[k][ aCfgLocaleStr ] );
+
+ // merge services list (previously configured to be listed first).
+ aCfgSvcs = lcl_MergeSeq( aCfgSvcs, aNewSvcs );
+
+/*
+ // there is at most one Hyphenator per language allowed
+ // to be configured, thus we only use the first one found.
+ if (k == 2 && aCfgSvcs.getLength() > 1)
+ aCfgSvcs.realloc(1);
+*/
+ aCurSvcs[k][ aCfgLocaleStr ] = aCfgSvcs;
+ }
+
+ //
+ // set last found services to currently available ones
+ //
+ for (i = 0; i < nAvailLocales; ++i)
+ {
+ Sequence< OUString > aSvcImplNames(
+ xLngSvcMgr->getAvailableServices( aService, pAvailLocale[i] ) );
+
+#if OSL_DEBUG_LEVEL > 1
+ INT32 nSvcs = aSvcImplNames.getLength();
+ const OUString *pSvcImplName = aSvcImplNames.getConstArray();
+ for (INT32 j = 0; j < nSvcs; ++j)
+ {
+ OUString aImplName( pSvcImplName[j] );
+ }
+#endif
+
+ OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
+ SvxLocaleToLanguage( pAvailLocale[i] ) ) );
+ aLastFoundSvcs[k][ aCfgLocaleStr ] = aSvcImplNames;
+ }
+ }
+
+ //
+ // write new data back to configuration
+ //
+ for (int k = 0; k < nNumServices; ++k)
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ const sal_Char *pSubNodeName = (i == 0) ? apCurLists[k] : apLastFoundLists[k];
+ OUString aSubNodeName( A2OU(pSubNodeName) );
+
+ list_entry_map_t &rCurMap = (i == 0) ? aCurSvcs[k] : aLastFoundSvcs[k];
+ list_entry_map_t::const_iterator aIt( rCurMap.begin() );
+ sal_Int32 nVals = static_cast< sal_Int32 >( rCurMap.size() );
+ Sequence< PropertyValue > aNewValues( nVals );
+ PropertyValue *pNewValue = aNewValues.getArray();
+ while (aIt != rCurMap.end())
+ {
+ OUString aCfgEntryName( aSubNodeName );
+ aCfgEntryName += OUString::valueOf( (sal_Unicode) '/' );
+ aCfgEntryName += (*aIt).first;
+
+#if OSL_DEBUG_LEVEL > 1
+ Sequence< OUString > aSvcImplNames( (*aIt).second );
+ INT32 nSvcs = aSvcImplNames.getLength();
+ const OUString *pSvcImplName = aSvcImplNames.getConstArray();
+ for (INT32 j = 0; j < nSvcs; ++j)
+ {
+ OUString aImplName( pSvcImplName[j] );
+ }
+#endif
+ pNewValue->Name = aCfgEntryName;
+ pNewValue->Value <<= (*aIt).second;
+ ++pNewValue;
+ ++aIt;
+ }
+ DBG_ASSERT( pNewValue - aNewValues.getArray() == nVals,
+ "possible mismatch of sequence size and property number" );
+
+ {
+ RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll - ReplaceSetProperties" );
+ // add new or replace existing entries.
+ BOOL bRes = aCfg.ReplaceSetProperties( aSubNodeName, aNewValues );
+ if (!bRes)
+ {
+#if OSL_DEBUG_LEVEL > 1
+ DBG_ERROR( "failed to set new configuration values" );
+#endif
+ }
+ }
+ }
+ }
+ DBG_ASSERT( nCurrentDataFilesChangedCheckValue != -1, "SvxLinguConfigUpdate::UpdateAll DataFilesChangedCheckValue not yet calculated!" );
+ Any aAny;
+
+ // for the time being (developer builds until OOo 3.0)
+ // we should always check for everything available
+ // otherwise we may miss a new installed extension dicitonary
+ // just because e.g. the spellchecker is not asked what
+ // languages it does support currently...
+ // Since the check is on-demand occuring and executed once it should
+ // not be too troublesome.
+ // In OOo 3.0 we will not need the respective code anymore at all.
+// aAny <<= nCurrentDataFilesChangedCheckValue;
+ aAny <<= (INT32) -1; // keep the value set to 'need to check'
+
+ aCfg.SetProperty( A2OU( "DataFilesChangedCheckValue" ), aAny );
+
+ //! Note 1: the new values are commited when the 'aCfg' object
+ //! gets destroyed.
+ //! Note 2: the new settings in the configuration get applied
+ //! because the 'LngSvcMgr' (in linguistic/source/lngsvcmgr.hxx)
+ //! listens to the configuration for changes of the relevant
+ //! properties and then applies the new settings.
+
+ // nothing needs to be done anymore
+ nNeedUpdating = 0;
+ }
+}
+
+
+INT32 SvxLinguConfigUpdate::CalcDataFilesChangedCheckValue()
+{
+ RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::CalcDataFilesChangedCheckValue" );
+
+ INT32 nHashVal = 0;
+ // nothing to be checked anymore since those old directory paths are gone by now
+ return nHashVal;
+}
+
+
+BOOL SvxLinguConfigUpdate::IsNeedUpdateAll( sal_Bool bForceCheck )
+{
+ RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::IsNeedUpdateAll" );
+ if (nNeedUpdating == -1 || bForceCheck ) // need to check if updating is necessary
+ {
+ // calculate hash value for current data files
+ nCurrentDataFilesChangedCheckValue = CalcDataFilesChangedCheckValue();
+
+ // compare hash value and check value to see if anything has changed
+ // and thus the configuration needs to be updated
+ SvtLinguOptions aLinguOpt;
+ SvtLinguConfig aCfg;
+ aCfg.GetOptions( aLinguOpt );
+ nNeedUpdating = (nCurrentDataFilesChangedCheckValue == aLinguOpt.nDataFilesChangedCheckValue) ? 0 : 1;
+ }
+ DBG_ASSERT( nNeedUpdating != -1,
+ "need for linguistic configuration update should have been already checked." );
+
+ return nNeedUpdating == 1;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+
+//! Dummy implementation in order to avoid loading of lingu DLL
+//! when only the XSupportedLocales interface is used.
+//! The dummy accesses the real implementation (and thus loading the DLL)
+//! when "real" work needs to be done only.
+class ThesDummy_Impl :
+ public cppu::WeakImplHelper1< XThesaurus >
+{
+ uno::Reference< XThesaurus > xThes; // the real one...
+ Sequence< Locale > *pLocaleSeq;
+
+ void GetCfgLocales();
+
+ void GetThes_Impl();
+
+public:
+ ThesDummy_Impl() : pLocaleSeq(0) {}
+ ~ThesDummy_Impl();
+
+ // XSupportedLocales
+ virtual ::com::sun::star::uno::Sequence<
+ ::com::sun::star::lang::Locale > SAL_CALL
+ getLocales()
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL
+ hasLocale( const ::com::sun::star::lang::Locale& rLocale )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XThesaurus
+ virtual ::com::sun::star::uno::Sequence<
+ ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XMeaning > > SAL_CALL
+ queryMeanings( const ::rtl::OUString& rTerm,
+ const ::com::sun::star::lang::Locale& rLocale,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+};
+
+
+ThesDummy_Impl::~ThesDummy_Impl()
+{
+ delete pLocaleSeq;
+}
+
+
+void ThesDummy_Impl::GetCfgLocales()
+{
+ if (!pLocaleSeq)
+ {
+ SvtLinguConfig aCfg;
+ String aNode( A2OU( "ServiceManager/ThesaurusList" ) );
+ Sequence < OUString > aNodeNames( aCfg.GetNodeNames( aNode ) );
+ const OUString *pNodeNames = aNodeNames.getConstArray();
+ INT32 nLen = aNodeNames.getLength();
+ pLocaleSeq = new Sequence< Locale >( nLen );
+ Locale *pLocale = pLocaleSeq->getArray();
+ for (INT32 i = 0; i < nLen; ++i)
+ {
+ pLocale[i] = SvxCreateLocale(
+ MsLangId::convertIsoStringToLanguage( pNodeNames[i] ) );
+ }
+ }
+}
+
+
+void ThesDummy_Impl::GetThes_Impl()
+{
+ // update configuration before accessing the service
+ if (SvxLinguConfigUpdate::IsNeedUpdateAll())
+ SvxLinguConfigUpdate::UpdateAll();
+
+ if (!xThes.is())
+ {
+ uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
+ if (xLngSvcMgr.is())
+ xThes = xLngSvcMgr->getThesaurus();
+
+ if (xThes.is())
+ {
+ // no longer needed...
+ delete pLocaleSeq; pLocaleSeq = 0;
+ }
+ }
+}
+
+
+uno::Sequence< lang::Locale > SAL_CALL
+ ThesDummy_Impl::getLocales()
+ throw(uno::RuntimeException)
+{
+ if (!SvxLinguConfigUpdate::IsNeedUpdateAll()) // configuration already update and thus lingu DLL's already loaded ?
+ GetThes_Impl();
+ if (xThes.is())
+ return xThes->getLocales();
+ else if (!pLocaleSeq) // if not already loaded save startup time by avoiding loading them now
+ GetCfgLocales();
+ return *pLocaleSeq;
+}
+
+
+sal_Bool SAL_CALL
+ ThesDummy_Impl::hasLocale( const lang::Locale& rLocale )
+ throw(uno::RuntimeException)
+{
+ if (!SvxLinguConfigUpdate::IsNeedUpdateAll()) // configuration already update and thus lingu DLL's already loaded ?
+ GetThes_Impl();
+ if (xThes.is())
+ return xThes->hasLocale( rLocale );
+ else if (!pLocaleSeq) // if not already loaded save startup time by avoiding loading them now
+ GetCfgLocales();
+ GetCfgLocales();
+ BOOL bFound = FALSE;
+ INT32 nLen = pLocaleSeq->getLength();
+ const Locale *pLocale = pLocaleSeq->getConstArray();
+ const Locale *pEnd = pLocale + nLen;
+ for ( ; pLocale < pEnd && !bFound; ++pLocale)
+ {
+ bFound = pLocale->Language == rLocale.Language &&
+ pLocale->Country == rLocale.Country &&
+ pLocale->Variant == rLocale.Variant;
+ }
+ return bFound;
+}
+
+
+uno::Sequence< uno::Reference< linguistic2::XMeaning > > SAL_CALL
+ ThesDummy_Impl::queryMeanings(
+ const rtl::OUString& rTerm,
+ const lang::Locale& rLocale,
+ const beans::PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetThes_Impl();
+ uno::Sequence< uno::Reference< linguistic2::XMeaning > > aRes;
+ DBG_ASSERT( xThes.is(), "Thesaurus missing" );
+ if (xThes.is())
+ aRes = xThes->queryMeanings( rTerm, rLocale, rProperties );
+ return aRes;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+//! Dummy implementation in order to avoid loading of lingu DLL.
+//! The dummy accesses the real implementation (and thus loading the DLL)
+//! when it needs to be done only.
+class SpellDummy_Impl :
+ public cppu::WeakImplHelper1< XSpellChecker1 >
+{
+ uno::Reference< XSpellChecker1 > xSpell; // the real one...
+
+ void GetSpell_Impl();
+
+public:
+
+ // XSupportedLanguages (for XSpellChecker1)
+ virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL
+ getLanguages()
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL
+ hasLanguage( sal_Int16 nLanguage )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XSpellChecker1 (same as XSpellChecker but sal_Int16 for language)
+ virtual sal_Bool SAL_CALL
+ isValid( const ::rtl::OUString& rWord, sal_Int16 nLanguage,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XSpellAlternatives > SAL_CALL
+ spell( const ::rtl::OUString& rWord, sal_Int16 nLanguage,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+};
+
+
+void SpellDummy_Impl::GetSpell_Impl()
+{
+ // update configuration before accessing the service
+ if (SvxLinguConfigUpdate::IsNeedUpdateAll())
+ SvxLinguConfigUpdate::UpdateAll();
+
+ if (!xSpell.is())
+ {
+ uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
+ if (xLngSvcMgr.is())
+ xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
+ }
+}
+
+
+uno::Sequence< sal_Int16 > SAL_CALL
+ SpellDummy_Impl::getLanguages()
+ throw(uno::RuntimeException)
+{
+ GetSpell_Impl();
+ if (xSpell.is())
+ return xSpell->getLanguages();
+ else
+ return uno::Sequence< sal_Int16 >();
+}
+
+
+sal_Bool SAL_CALL
+ SpellDummy_Impl::hasLanguage( sal_Int16 nLanguage )
+ throw(uno::RuntimeException)
+{
+ GetSpell_Impl();
+ BOOL bRes = FALSE;
+ if (xSpell.is())
+ bRes = xSpell->hasLanguage( nLanguage );
+ return bRes;
+}
+
+
+sal_Bool SAL_CALL
+ SpellDummy_Impl::isValid( const rtl::OUString& rWord, sal_Int16 nLanguage,
+ const beans::PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetSpell_Impl();
+ BOOL bRes = TRUE;
+ if (xSpell.is())
+ bRes = xSpell->isValid( rWord, nLanguage, rProperties );
+ return bRes;
+}
+
+
+uno::Reference< linguistic2::XSpellAlternatives > SAL_CALL
+ SpellDummy_Impl::spell( const rtl::OUString& rWord, sal_Int16 nLanguage,
+ const beans::PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetSpell_Impl();
+ uno::Reference< linguistic2::XSpellAlternatives > xRes;
+ if (xSpell.is())
+ xRes = xSpell->spell( rWord, nLanguage, rProperties );
+ return xRes;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+//! Dummy implementation in order to avoid loading of lingu DLL.
+//! The dummy accesses the real implementation (and thus loading the DLL)
+//! when it needs to be done only.
+class HyphDummy_Impl :
+ public cppu::WeakImplHelper1< XHyphenator >
+{
+ uno::Reference< XHyphenator > xHyph; // the real one...
+
+ void GetHyph_Impl();
+
+public:
+
+ // XSupportedLocales
+ virtual ::com::sun::star::uno::Sequence<
+ ::com::sun::star::lang::Locale > SAL_CALL
+ getLocales()
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL
+ hasLocale( const ::com::sun::star::lang::Locale& rLocale )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XHyphenator
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenatedWord > SAL_CALL
+ hyphenate( const ::rtl::OUString& rWord,
+ const ::com::sun::star::lang::Locale& rLocale,
+ sal_Int16 nMaxLeading,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenatedWord > SAL_CALL
+ queryAlternativeSpelling( const ::rtl::OUString& rWord,
+ const ::com::sun::star::lang::Locale& rLocale,
+ sal_Int16 nIndex,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XPossibleHyphens > SAL_CALL
+ createPossibleHyphens(
+ const ::rtl::OUString& rWord,
+ const ::com::sun::star::lang::Locale& rLocale,
+ const ::com::sun::star::beans::PropertyValues& rProperties )
+ throw(::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::uno::RuntimeException);
+};
+
+
+void HyphDummy_Impl::GetHyph_Impl()
+{
+ // update configuration before accessing the service
+ if (SvxLinguConfigUpdate::IsNeedUpdateAll())
+ SvxLinguConfigUpdate::UpdateAll();
+
+ if (!xHyph.is())
+ {
+ uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
+ if (xLngSvcMgr.is())
+ xHyph = xLngSvcMgr->getHyphenator();
+ }
+}
+
+
+uno::Sequence< lang::Locale > SAL_CALL
+ HyphDummy_Impl::getLocales()
+ throw(uno::RuntimeException)
+{
+ GetHyph_Impl();
+ if (xHyph.is())
+ return xHyph->getLocales();
+ else
+ return uno::Sequence< lang::Locale >();
+}
+
+
+sal_Bool SAL_CALL
+ HyphDummy_Impl::hasLocale( const lang::Locale& rLocale )
+ throw(uno::RuntimeException)
+{
+ GetHyph_Impl();
+ BOOL bRes = FALSE;
+ if (xHyph.is())
+ bRes = xHyph->hasLocale( rLocale );
+ return bRes;
+}
+
+
+uno::Reference< linguistic2::XHyphenatedWord > SAL_CALL
+ HyphDummy_Impl::hyphenate(
+ const rtl::OUString& rWord,
+ const lang::Locale& rLocale,
+ sal_Int16 nMaxLeading,
+ const beans::PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetHyph_Impl();
+ uno::Reference< linguistic2::XHyphenatedWord > xRes;
+ if (xHyph.is())
+ xRes = xHyph->hyphenate( rWord, rLocale, nMaxLeading, rProperties );
+ return xRes;
+}
+
+
+uno::Reference< linguistic2::XHyphenatedWord > SAL_CALL
+ HyphDummy_Impl::queryAlternativeSpelling(
+ const rtl::OUString& rWord,
+ const lang::Locale& rLocale,
+ sal_Int16 nIndex,
+ const PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetHyph_Impl();
+ uno::Reference< linguistic2::XHyphenatedWord > xRes;
+ if (xHyph.is())
+ xRes = xHyph->queryAlternativeSpelling( rWord, rLocale, nIndex, rProperties );
+ return xRes;
+}
+
+
+uno::Reference< linguistic2::XPossibleHyphens > SAL_CALL
+ HyphDummy_Impl::createPossibleHyphens(
+ const rtl::OUString& rWord,
+ const lang::Locale& rLocale,
+ const beans::PropertyValues& rProperties )
+ throw(lang::IllegalArgumentException,
+ uno::RuntimeException)
+{
+ GetHyph_Impl();
+ uno::Reference< linguistic2::XPossibleHyphens > xRes;
+ if (xHyph.is())
+ xRes = xHyph->createPossibleHyphens( rWord, rLocale, rProperties );
+ return xRes;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+
+typedef cppu::WeakImplHelper1 < XEventListener > LinguMgrAppExitLstnrBaseClass;
+
+class LinguMgrAppExitLstnr : public LinguMgrAppExitLstnrBaseClass
+{
+ uno::Reference< XComponent > xDesktop;
+
+public:
+ LinguMgrAppExitLstnr();
+ virtual ~LinguMgrAppExitLstnr();
+
+ virtual void AtExit() = 0;
+
+
+ // lang::XEventListener
+ virtual void SAL_CALL disposing(const EventObject& rSource)
+ throw( RuntimeException );
+};
+
+LinguMgrAppExitLstnr::LinguMgrAppExitLstnr()
+{
+ // add object to frame::Desktop EventListeners in order to properly call
+ // the AtExit function at appliction exit.
+
+ uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory();
+ if ( xMgr.is() )
+ {
+ xDesktop = uno::Reference< XComponent > ( xMgr->createInstance(
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.frame.Desktop" ) ) ), UNO_QUERY ) ;
+ if (xDesktop.is())
+ xDesktop->addEventListener( this );
+ }
+}
+
+LinguMgrAppExitLstnr::~LinguMgrAppExitLstnr()
+{
+ if (xDesktop.is())
+ {
+ xDesktop->removeEventListener( this );
+ xDesktop = NULL; //! release reference to desktop
+ }
+ DBG_ASSERT(!xDesktop.is(), "reference to desktop should be realeased");
+}
+
+void LinguMgrAppExitLstnr::disposing(const EventObject& rSource)
+ throw( RuntimeException )
+{
+ if (xDesktop.is() && rSource.Source == xDesktop)
+ {
+ xDesktop->removeEventListener( this );
+ xDesktop = NULL; //! release reference to desktop
+
+ AtExit();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+class LinguMgrExitLstnr : public LinguMgrAppExitLstnr
+{
+public:
+ virtual void AtExit();
+};
+
+void LinguMgrExitLstnr::AtExit()
+{
+ // release references
+ LinguMgr::xLngSvcMgr = 0;
+ LinguMgr::xSpell = 0;
+ LinguMgr::xHyph = 0;
+ LinguMgr::xThes = 0;
+ LinguMgr::xDicList = 0;
+ LinguMgr::xProp = 0;
+ LinguMgr::xIgnoreAll = 0;
+ LinguMgr::xChangeAll = 0;
+
+ LinguMgr::bExiting = sal_True;
+
+ //TL:TODO: MBA fragen wie ich ohne Absturz hier meinen Speicher
+ // wieder freibekomme...
+ //delete LinguMgr::pExitLstnr;
+ LinguMgr::pExitLstnr = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+
+// static member initialization
+LinguMgrExitLstnr * LinguMgr::pExitLstnr = 0;
+sal_Bool LinguMgr::bExiting = sal_False;
+uno::Reference< XLinguServiceManager > LinguMgr::xLngSvcMgr = 0;
+uno::Reference< XSpellChecker1 > LinguMgr::xSpell = 0;
+uno::Reference< XHyphenator > LinguMgr::xHyph = 0;
+uno::Reference< XThesaurus > LinguMgr::xThes = 0;
+uno::Reference< XDictionaryList > LinguMgr::xDicList = 0;
+uno::Reference< XPropertySet > LinguMgr::xProp = 0;
+uno::Reference< XDictionary > LinguMgr::xIgnoreAll = 0;
+uno::Reference< XDictionary > LinguMgr::xChangeAll = 0;
+
+
+uno::Reference< XLinguServiceManager > LinguMgr::GetLngSvcMgr()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ if (!xLngSvcMgr.is())
+ xLngSvcMgr = GetLngSvcMgr_Impl();
+
+ return xLngSvcMgr;
+}
+
+
+uno::Reference< XSpellChecker1 > LinguMgr::GetSpellChecker()
+{
+ return xSpell.is() ? xSpell : GetSpell();
+}
+
+uno::Reference< XHyphenator > LinguMgr::GetHyphenator()
+{
+ return xHyph.is() ? xHyph : GetHyph();
+}
+
+uno::Reference< XThesaurus > LinguMgr::GetThesaurus()
+{
+ return xThes.is() ? xThes : GetThes();
+}
+
+uno::Reference< XDictionaryList > LinguMgr::GetDictionaryList()
+{
+ return xDicList.is() ? xDicList : GetDicList();
+}
+
+uno::Reference< XPropertySet > LinguMgr::GetLinguPropertySet()
+{
+ return xProp.is() ? xProp : GetProp();
+}
+
+uno::Reference< XDictionary > LinguMgr::GetStandardDic()
+{
+ //! don't hold reference to this
+ //! (it may be removed from dictionary list and needs to be
+ //! created empty if accessed again)
+ return GetStandard();
+}
+
+uno::Reference< XDictionary > LinguMgr::GetIgnoreAllList()
+{
+ return xIgnoreAll.is() ? xIgnoreAll : GetIgnoreAll();
+}
+
+uno::Reference< XDictionary > LinguMgr::GetChangeAllList()
+{
+ return xChangeAll.is() ? xChangeAll : GetChangeAll();
+}
+
+uno::Reference< XSpellChecker1 > LinguMgr::GetSpell()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ //! use dummy implementation in order to avoid loading of lingu DLL
+ xSpell = new SpellDummy_Impl;
+
+/* if (!xLngSvcMgr.is())
+ xLngSvcMgr = GetLngSvcMgr_Impl();
+
+ if (xLngSvcMgr.is())
+ {
+ xSpell = uno::Reference< XSpellChecker1 > (
+ xLngSvcMgr->getSpellChecker(), UNO_QUERY );
+ }
+*/
+ return xSpell;
+}
+
+uno::Reference< XHyphenator > LinguMgr::GetHyph()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ //! use dummy implementation in order to avoid loading of lingu DLL
+ xHyph = new HyphDummy_Impl;
+
+/*
+ if (!xLngSvcMgr.is())
+ xLngSvcMgr = GetLngSvcMgr_Impl();
+
+ if (xLngSvcMgr.is())
+ {
+ xHyph = xLngSvcMgr->getHyphenator();
+ }
+*/
+ return xHyph;
+}
+
+uno::Reference< XThesaurus > LinguMgr::GetThes()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ //! use dummy implementation in order to avoid loading of lingu DLL
+ //! when only the XSupportedLocales interface is used.
+ //! The dummy accesses the real implementation (and thus loading the DLL)
+ //! when "real" work needs to be done only.
+ xThes = new ThesDummy_Impl;
+/*
+ if (!xLngSvcMgr.is())
+ xLngSvcMgr = GetLngSvcMgr_Impl();
+
+ if (xLngSvcMgr.is())
+ {
+ xThes = xLngSvcMgr->getThesaurus();
+ }
+*/
+ return xThes;
+}
+
+
+void LinguMgr::UpdateAll()
+{
+}
+
+
+uno::Reference< XDictionaryList > LinguMgr::GetDicList()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ uno::Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ xDicList = uno::Reference< XDictionaryList > ( xMgr->createInstance(
+ A2OU("com.sun.star.linguistic2.DictionaryList") ), UNO_QUERY );
+ }
+ return xDicList;
+}
+
+uno::Reference< XPropertySet > LinguMgr::GetProp()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ uno::Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() );
+ if (xMgr.is())
+ {
+ xProp = uno::Reference< XPropertySet > ( xMgr->createInstance(
+ A2OU("com.sun.star.linguistic2.LinguProperties") ), UNO_QUERY );
+ }
+ return xProp;
+}
+
+uno::Reference< XDictionary > LinguMgr::GetIgnoreAll()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ uno::Reference< XDictionaryList > xTmpDicList( GetDictionaryList() );
+ if (xTmpDicList.is())
+ {
+ xIgnoreAll = uno::Reference< XDictionary > ( xTmpDicList->getDictionaryByName(
+ A2OU("IgnoreAllList") ), UNO_QUERY );
+ }
+ return xIgnoreAll;
+}
+
+uno::Reference< XDictionary > LinguMgr::GetChangeAll()
+{
+ if (bExiting)
+ return 0;
+
+ if (!pExitLstnr)
+ pExitLstnr = new LinguMgrExitLstnr;
+
+ uno::Reference< XDictionaryList > _xDicList( GetDictionaryList() , UNO_QUERY );
+ if (_xDicList.is())
+ {
+ xChangeAll = uno::Reference< XDictionary > (
+ _xDicList->createDictionary(
+ A2OU("ChangeAllList"),
+ SvxCreateLocale( LANGUAGE_NONE ),
+ DictionaryType_NEGATIVE, String() ), UNO_QUERY );
+ }
+ return xChangeAll;
+}
+
+uno::Reference< XDictionary > LinguMgr::GetStandard()
+{
+ // Tries to return a dictionary which may hold positive entries is
+ // persistent and not read-only.
+
+ if (bExiting)
+ return 0;
+
+ uno::Reference< XDictionaryList > xTmpDicList( GetDictionaryList() );
+ if (!xTmpDicList.is())
+ return NULL;
+
+ const OUString aDicName( RTL_CONSTASCII_USTRINGPARAM( "standard.dic" ) );
+ uno::Reference< XDictionary > xDic( xTmpDicList->getDictionaryByName( aDicName ),
+ UNO_QUERY );
+ if (!xDic.is())
+ {
+ // try to create standard dictionary
+ uno::Reference< XDictionary > xTmp;
+ try
+ {
+ xTmp = xTmpDicList->createDictionary( aDicName,
+ SvxCreateLocale( LANGUAGE_NONE ),
+ DictionaryType_POSITIVE,
+ linguistic::GetWritableDictionaryURL( aDicName ) );
+ }
+ catch(com::sun::star::uno::Exception &)
+ {
+ }
+
+ // add new dictionary to list
+ if (xTmp.is())
+ xTmpDicList->addDictionary( xTmp );
+ xDic = uno::Reference< XDictionary > ( xTmp, UNO_QUERY );
+ }
+#if OSL_DEBUG_LEVEL > 1
+ uno::Reference< XStorable > xStor( xDic, UNO_QUERY );
+ DBG_ASSERT( xDic.is() && xDic->getDictionaryType() == DictionaryType_POSITIVE,
+ "wrong dictionary type");
+ DBG_ASSERT( xDic.is() && SvxLocaleToLanguage( xDic->getLocale() ) == LANGUAGE_NONE,
+ "wrong dictionary language");
+ DBG_ASSERT( !xStor.is() || (xStor->hasLocation() && !xStor->isReadonly()),
+ "dictionary not editable" );
+#endif
+
+ return xDic;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+uno::Reference< XSpellChecker1 > SvxGetSpellChecker()
+{
+ return LinguMgr::GetSpellChecker();
+}
+
+uno::Reference< XHyphenator > SvxGetHyphenator()
+{
+ return LinguMgr::GetHyphenator();
+}
+
+uno::Reference< XThesaurus > SvxGetThesaurus()
+{
+ return LinguMgr::GetThesaurus();
+}
+
+uno::Reference< XDictionaryList > SvxGetDictionaryList()
+{
+ return LinguMgr::GetDictionaryList();
+}
+
+uno::Reference< XPropertySet > SvxGetLinguPropertySet()
+{
+ return LinguMgr::GetLinguPropertySet();
+}
+
+//TL:TODO: remove argument or provide SvxGetIgnoreAllList with the same one
+uno::Reference< XDictionary > SvxGetOrCreatePosDic(
+ uno::Reference< XDictionaryList > /* xDicList */ )
+{
+ return LinguMgr::GetStandardDic();
+}
+
+uno::Reference< XDictionary > SvxGetIgnoreAllList()
+{
+ return LinguMgr::GetIgnoreAllList();
+}
+
+uno::Reference< XDictionary > SvxGetChangeAllList()
+{
+ return LinguMgr::GetChangeAllList();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+
+#include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
+
+SvxAlternativeSpelling SvxGetAltSpelling(
+ const ::com::sun::star::uno::Reference<
+ ::com::sun::star::linguistic2::XHyphenatedWord > & rHyphWord )
+{
+ SvxAlternativeSpelling aRes;
+ if (rHyphWord.is() && rHyphWord->isAlternativeSpelling())
+ {
+ OUString aWord( rHyphWord->getWord() ),
+ aAltWord( rHyphWord->getHyphenatedWord() );
+ INT16 nHyphenationPos = rHyphWord->getHyphenationPos(),
+ nHyphenPos = rHyphWord->getHyphenPos();
+ INT16 nLen = (INT16)aWord.getLength();
+ INT16 nAltLen = (INT16)aAltWord.getLength();
+ const sal_Unicode *pWord = aWord.getStr(),
+ *pAltWord = aAltWord.getStr();
+
+ // count number of chars from the left to the
+ // hyphenation pos / hyphen pos that are equal
+ INT16 nL = 0;
+ while (nL <= nHyphenationPos && nL <= nHyphenPos
+ && pWord[ nL ] == pAltWord[ nL ])
+ ++nL;
+ // count number of chars from the right to the
+ // hyphenation pos / hyphen pos that are equal
+ INT16 nR = 0;
+ INT32 nIdx = nLen - 1;
+ INT32 nAltIdx = nAltLen - 1;
+ while (nIdx > nHyphenationPos && nAltIdx > nHyphenPos
+ && pWord[ nIdx-- ] == pAltWord[ nAltIdx-- ])
+ ++nR;
+
+ aRes.aReplacement = OUString( aAltWord.copy( nL, nAltLen - nL - nR ) );
+ aRes.nChangedPos = (INT16) nL;
+ aRes.nChangedLength = nLen - nL - nR;
+ aRes.bIsAltSpelling = TRUE;
+ aRes.xHyphWord = rHyphWord;
+ }
+ return aRes;
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+
+SvxDicListChgClamp::SvxDicListChgClamp( uno::Reference< XDictionaryList > &rxDicList ) :
+ xDicList ( rxDicList )
+{
+ if (xDicList.is())
+ {
+ xDicList->beginCollectEvents();
+ }
+}
+
+SvxDicListChgClamp::~SvxDicListChgClamp()
+{
+ if (xDicList.is())
+ {
+ xDicList->endCollectEvents();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+short SvxDicError( Window *pParent, sal_Int16 nError )
+{
+ short nRes = 0;
+ if (DIC_ERR_NONE != nError)
+ {
+ int nRid;
+ switch (nError)
+ {
+ case DIC_ERR_FULL : nRid = RID_SVXSTR_DIC_ERR_FULL; break;
+ case DIC_ERR_READONLY : nRid = RID_SVXSTR_DIC_ERR_READONLY; break;
+ default:
+ nRid = RID_SVXSTR_DIC_ERR_UNKNOWN;
+ DBG_ASSERT(0, "unexpected case");
+ }
+ nRes = InfoBox( pParent, EE_RESSTR( nRid ) ).Execute();
+ }
+ return nRes;
+}
+
+LanguageType SvxLocaleToLanguage( const Locale& rLocale )
+{
+ // empty Locale -> LANGUAGE_NONE
+ if ( rLocale.Language.getLength() == 0 )
+ return LANGUAGE_NONE;
+
+ return MsLangId::convertLocaleToLanguage( rLocale );
+}
+
+Locale& SvxLanguageToLocale( Locale& rLocale, LanguageType eLang )
+{
+ if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */)
+ MsLangId::convertLanguageToLocale( eLang, rLocale );
+ else
+ rLocale = Locale();
+
+ return rLocale;
+}
+
+Locale SvxCreateLocale( LanguageType eLang )
+{
+ Locale aLocale;
+ if ( eLang != LANGUAGE_NONE /* && eLang != LANGUAGE_SYSTEM */)
+ MsLangId::convertLanguageToLocale( eLang, aLocale );
+
+ return aLocale;
+}
+
+