summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editeng/CppunitTest_editeng_lookuptree.mk71
-rw-r--r--editeng/Library_editeng.mk5
-rw-r--r--editeng/Module_editeng.mk3
-rw-r--r--editeng/Package_inc.mk7
-rw-r--r--editeng/inc/editeng/LatinLookupTree.hxx76
-rw-r--r--editeng/inc/editeng/LatinTreeNode.hxx48
-rw-r--r--editeng/inc/editeng/LookupTree.hxx95
-rw-r--r--editeng/inc/editeng/Node.hxx102
-rw-r--r--editeng/inc/editeng/TreeHead.hxx49
-rw-r--r--editeng/qa/lookuptree/lookuptree_test.cxx225
-rw-r--r--editeng/source/lookuptree/LatinLookupTree.cxx240
-rw-r--r--editeng/source/lookuptree/LatinTreeNode.cxx112
-rw-r--r--editeng/source/lookuptree/Node.cxx213
13 files changed, 1243 insertions, 3 deletions
diff --git a/editeng/CppunitTest_editeng_lookuptree.mk b/editeng/CppunitTest_editeng_lookuptree.mk
new file mode 100644
index 000000000000..a69999ee235a
--- /dev/null
+++ b/editeng/CppunitTest_editeng_lookuptree.mk
@@ -0,0 +1,71 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# 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.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,editeng_lookuptree))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,editeng_lookuptree, \
+ editeng/qa/lookuptree/lookuptree_test \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,editeng_lookuptree, \
+ xo \
+ basegfx \
+ editeng \
+ lng \
+ svt \
+ tk \
+ vcl \
+ svl \
+ sot \
+ utl \
+ tl \
+ comphelper \
+ ucbhelper \
+ cppuhelper \
+ cppu \
+ sal \
+ salhelper \
+ i18nisolang1 \
+ i18nutil \
+ $(gb_STDLIBS) \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,editeng_lookuptree,\
+ icuuc \
+))
+
+$(eval $(call gb_CppunitTest_set_include,editeng_lookuptree,\
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,editeng_lookuptree,\
+ offapi \
+ udkapi \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/editeng/Library_editeng.mk b/editeng/Library_editeng.mk
index 276e0625ad7c..81164b94c11c 100644
--- a/editeng/Library_editeng.mk
+++ b/editeng/Library_editeng.mk
@@ -2,7 +2,7 @@
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
+#
# Copyright 2000, 2011 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
@@ -125,6 +125,9 @@ $(eval $(call gb_Library_add_exception_objects,editeng,\
editeng/source/uno/unoviwou \
editeng/source/xml/xmltxtexp \
editeng/source/xml/xmltxtimp \
+ editeng/source/lookuptree/LatinLookupTree \
+ editeng/source/lookuptree/LatinTreeNode \
+ editeng/source/lookuptree/Node \
))
# add libraries to be linked to editeng; again these names need to be given as
diff --git a/editeng/Module_editeng.mk b/editeng/Module_editeng.mk
index b7670989d4ba..eff4df4ce916 100644
--- a/editeng/Module_editeng.mk
+++ b/editeng/Module_editeng.mk
@@ -2,7 +2,7 @@
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
+#
# Copyright 2000, 2011 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
@@ -39,6 +39,7 @@ $(eval $(call gb_Module_add_targets,editeng,\
$(eval $(call gb_Module_add_check_targets,editeng,\
CppunitTest_editeng_core \
CppunitTest_editeng_borderline \
+ CppunitTest_editeng_lookuptree \
))
# add any subsequent checks (e.g. complex tests) here
diff --git a/editeng/Package_inc.mk b/editeng/Package_inc.mk
index 300e2ae89c9f..653effb30333 100644
--- a/editeng/Package_inc.mk
+++ b/editeng/Package_inc.mk
@@ -2,7 +2,7 @@
#*************************************************************************
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
+#
# Copyright 2000, 2011 Oracle and/or its affiliates.
#
# OpenOffice.org - a multi-platform office productivity suite
@@ -153,5 +153,10 @@ $(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/widwitem.hxx,editeng/w
$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/writingmodeitem.hxx,editeng/writingmodeitem.hxx))
$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/wrlmitem.hxx,editeng/wrlmitem.hxx))
$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/xmlcnitm.hxx,editeng/xmlcnitm.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/LookupTree.hxx,editeng/LookupTree.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/Node.hxx,editeng/Node.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/TreeHead.hxx,editeng/TreeHead.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/LatinLookupTree.hxx,editeng/LatinLookupTree.hxx))
+$(eval $(call gb_Package_add_file,editeng_inc,inc/editeng/LatinTreeNode.hxx,editeng/LatinTreeNode.hxx))
# vim: set noet sw=4 ts=4:
diff --git a/editeng/inc/editeng/LatinLookupTree.hxx b/editeng/inc/editeng/LatinLookupTree.hxx
new file mode 100644
index 000000000000..373152c510c0
--- /dev/null
+++ b/editeng/inc/editeng/LatinLookupTree.hxx
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef LATINLOOKUPTREE_HXX
+#define LATINLOOKUPTREE_HXX
+
+#include <editeng/LookupTree.hxx>
+#include <editeng/TreeHead.hxx>
+#include <editeng/editengdllapi.h>
+
+using namespace rtl;
+
+/**
+ * LatinLookupTree implements a tree that is optimized for storing and looking
+ * up words that mainly consist of roman characters, although any other
+ * language can be handled, too.
+ */
+class EDITENG_DLLPUBLIC LatinLookupTree : public LookupTree, public TreeHead
+{
+public:
+
+ explicit LatinLookupTree(OUString sLanguage);
+ ~LatinLookupTree();
+
+
+ /* =================== Implemented Virtuals From LookupTree =================== */
+ void returnToRoot();
+ void gotoNode(OUString sNode);
+ void advance(const sal_Unicode a);
+ void goBack();
+ void insert(OUString sKey, const int nProbability = 1);
+ void insert(const int nProbability = 1);
+ void remove(OUString sKey);
+ OUString suggestAutoCompletion() const;
+ void clear();
+
+ /* =================== Implemented Virtuals From Node =================== */
+ bool isSeparatedlyHandled(const sal_Unicode cKey) const;
+ Node*& getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder = false);
+ void evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const;
+ void freeMemory();
+
+
+ /* =================== Implemented Virtual From TreeHead =================== */
+ Node* newNode(Node* pParent, const sal_Unicode cKey, const int nProbability = 0);
+
+ /* =================== Member Variables =================== */
+ // position of lower case letter 'a' within the selected char encoding.
+ static const unsigned int our_nLowerCaseA;
+
+ // position of upper case letter 'A' within the selected char encoding.
+ static const unsigned int our_nUpperCaseA;
+
+private:
+ Node* m_pLeaves[52]; // handles [a-z] and [A-Z]
+};
+
+#endif // LATINLOOKUPTREE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/inc/editeng/LatinTreeNode.hxx b/editeng/inc/editeng/LatinTreeNode.hxx
new file mode 100644
index 000000000000..5e406858697c
--- /dev/null
+++ b/editeng/inc/editeng/LatinTreeNode.hxx
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef LATINTREENODE_HXX
+#define LATINTREENODE_HXX
+
+#include <editeng/Node.hxx>
+
+/**
+ * LatinTreeNode represents a node within a LatinLookupTree. As en external
+ * caller, you should never have to do anything with this class directly.
+ * Use the class LatinLookupTree instead for constructing a new tree.
+ */
+class LatinTreeNode : public Node
+{
+public:
+ explicit LatinTreeNode(TreeHead *pHead, Node* pParent, const sal_Unicode cKey, const int nProbability = 0);
+ ~LatinTreeNode();
+
+ /* =================== Implemented Virtuals From Node =================== */
+ bool isSeparatedlyHandled(const sal_Unicode cKey) const;
+ Node*& getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder = false);
+ void evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const;
+ void freeMemory();
+
+private:
+ Node* m_pLeaves[26]; // handles [a-z]
+};
+
+#endif // LATINTREENODE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/inc/editeng/LookupTree.hxx b/editeng/inc/editeng/LookupTree.hxx
new file mode 100644
index 000000000000..95abcf25d6f8
--- /dev/null
+++ b/editeng/inc/editeng/LookupTree.hxx
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef LOOKUPTREE_H
+#define LOOKUPTREE_H
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <editeng/editengdllapi.h>
+
+/** LookupTree is an interface class that allows for unified access to tree
+ * structures used for storing dictionnary words as well as their respective
+ * probabilities.
+ * It allows you to insert or remove words from the tree, navigate threw the
+ * tree along its branches and request for a suggestion for autocompletion
+ * according to the position within the tree.
+ * It also allows you to attribute a specific language to each tree so that
+ * it is possible to serve the correct auto completions even within a document
+ * that contains content in more than one language.
+ */
+class EDITENG_DLLPUBLIC LookupTree
+{
+public:
+ explicit inline LookupTree(OUString sLanguage);
+ virtual ~LookupTree() {}
+
+ inline OUString language() const;
+
+ // Resets the current item to root.
+ virtual void returnToRoot() = 0;
+
+ // Advances from the root position key by key towards the node keyed with
+ // the last char of sKey.
+ virtual void gotoNode(OUString sNode) = 0;
+
+ // Advances from the current position towards the node keyed with cKey.
+ virtual void advance(const sal_Unicode cKey) = 0;
+
+ // Sets the focus to the parent of the current node. Removes the current
+ // node if it is invalid.
+ virtual void goBack() = 0;
+
+ // Inserts a complete keyword starting from the root node of the tree.
+ // Does not change the current position within the tree.
+ virtual void insert(OUString sKey, const int nProbability = 1) = 0;
+
+ // Inserts a keyword with the given probability at the current position
+ // within the tree. Does not change the current position within the tree.
+ virtual void insert(const int nProbability = 1) = 0;
+
+ // Removes a complete keyword starting from the root node of the tree.
+ // Does not change the current position within the tree.
+ virtual void remove(OUString sKey) = 0;
+
+ // Returns the suggested autocompletion for the current location within
+ // the tree.
+ virtual OUString suggestAutoCompletion() const = 0;
+
+ // Clears the tree and removes any information it contains.
+ virtual void clear() = 0;
+
+
+private:
+ const OUString m_sLanguage; // language handled by this tree
+};
+
+LookupTree::LookupTree(OUString sLanguage) :
+ m_sLanguage( sLanguage )
+{
+}
+
+OUString LookupTree::language() const
+{
+ return m_sLanguage;
+}
+
+#endif // LOOKUPTREE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/inc/editeng/Node.hxx b/editeng/inc/editeng/Node.hxx
new file mode 100644
index 000000000000..3159e48a99b7
--- /dev/null
+++ b/editeng/inc/editeng/Node.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef NODE_HXX
+#define NODE_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <list>
+
+class TreeHead;
+
+/**
+ * Node represents a node within a LookupTree. As en external caller, you
+ * should never have to do anything with this class directly.
+ * Use any of the classes derived from LookupTree instead for constructing a
+ * new tree.
+ */
+class Node
+{
+public:
+ //explicit Node(TreeHead* const pHead);
+ explicit Node(TreeHead* const pHead, Node* const pParent = NULL,
+ const sal_Unicode cKey = 0, const int nProbability = 0);
+
+ virtual ~Node();
+
+ // Removes the specified child from this node. Make sure you may remove it
+ // before doing so.
+ void removeChild(Node*& pChild);
+
+ // Inserts a complete keyword starting from this node of the tree.
+ void insertKey(OUString sKey, const int nProbability);
+ // Removes a complete keyword starting from this node of the tree.
+ void removeKey(OUString sKey);
+
+ // Returns the child node keyed with cKey.
+ Node* advanceKey(const sal_Unicode cKey);
+
+ // Use this to inform a parent about its child having changed.
+ // Call this only with nProbability = 0 if you have made sure the node can
+ // be removed.
+ void childHasChanged(Node* pChild, const int nProbability, bool bAllowRemoval = false);
+
+ // Rechose the node that is suggested for auto-completion
+ void reevaluateSuggestion(bool& bNodeProbabilityChanged);
+
+
+ /* =================== Virtuals =================== */
+ virtual bool isSeparatedlyHandled(const sal_Unicode cKey) const = 0;
+
+ // Returns a reference to the pointer to the child node for the requested
+ // char. Returns NULL if no such child could be found.
+ // IMPORTANT: In the latter case, you may NOT overwrite the return value,
+ // if you did not set bCreatePlaceholder to true.
+ virtual Node*& getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder = false) = 0;
+
+ // Sets nSuggest to the highest probability within the subtree and pSuggest
+ // to point to the (first) node with this probability.
+ virtual void evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const = 0;
+
+ // Removes all child nodes and clears all memory.
+ virtual void freeMemory() = 0;
+
+ /* =================== Member Variables =================== */
+ const sal_Unicode m_cKey; // the char represented by this node
+ int m_nKeyProbability; // the number of occurrences of this key
+
+ // the highest KeyProbability in the tree sprouting from this node
+ int m_nHighestProbaInSubtree;
+
+ Node* const m_pParent; // the parent of this node
+ Node* m_pSuggest; // next node in chain to the suggested autocompletion
+
+ TreeHead* const m_pHead; // head of the tree
+
+ unsigned short m_nChildren; // the number of children of the node
+ std::list<Node*> m_lChildren; // all chars not handled by array
+
+ // Allows returning a reference to a valid Null pointer. May NOT be overwritten.
+ static Node* our_pNodeNullPointer;
+};
+
+#endif // NODE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/inc/editeng/TreeHead.hxx b/editeng/inc/editeng/TreeHead.hxx
new file mode 100644
index 000000000000..12c8b33c8d66
--- /dev/null
+++ b/editeng/inc/editeng/TreeHead.hxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef TREEHEAD_HXX
+#define TREEHEAD_HXX
+
+#include <editeng/Node.hxx>
+
+/**
+ * Represents the root node of a LookupTree.
+ */
+class TreeHead : public Node
+{
+public:
+ explicit inline TreeHead();
+ virtual ~TreeHead() {}
+
+ /* =================== Virtuals =================== */
+ virtual Node* newNode(Node* pParent, const sal_Unicode cKey, const int nProbability = 0) = 0;
+
+ /* =================== Member Variables =================== */
+ Node* m_pCurrent; // current location within the tree
+};
+
+TreeHead::TreeHead() :
+ Node( this ),
+ m_pCurrent( this )
+{
+}
+
+#endif // TREEHEAD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/qa/lookuptree/lookuptree_test.cxx b/editeng/qa/lookuptree/lookuptree_test.cxx
new file mode 100644
index 000000000000..9ca8bdcc38d9
--- /dev/null
+++ b/editeng/qa/lookuptree/lookuptree_test.cxx
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/types.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <editeng/LookupTree.hxx>
+#include <editeng/LatinLookupTree.hxx>
+
+namespace {
+
+class LookupTreeTest : public CppUnit::TestFixture
+{
+ public:
+ void test();
+
+ CPPUNIT_TEST_SUITE(LookupTreeTest);
+ CPPUNIT_TEST(test);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LookupTreeTest);
+
+void LookupTreeTest::test()
+{
+ LookupTree* a = new LatinLookupTree( "a" );
+
+ a->insert( OUString("vorschlagnummer1"), 2 );
+ a->insert( OUString("vorschlagnummer12") );
+ a->insert( OUString("vorschlagnummer2") );
+
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer1"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlagnummer12") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer12"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlagnummer2") );
+ a->insert( OUString("vorschlagnummer2") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer2"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlag"), 15 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlagnummer2"), 16 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer2"), a->suggestAutoCompletion() );
+
+ a->remove( OUString("vorschlagnummer2") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlag20"), 20 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag20"), a->suggestAutoCompletion() );
+
+ a->remove( OUString("vorschlag20") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlagn"), 14 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->remove( OUString("vorschlag") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagn"), a->suggestAutoCompletion() );
+
+ a->remove( OUString("vorschlagn") );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer12"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("aber"), 1 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer12"), a->suggestAutoCompletion() );
+
+ a->advance( 'a' );
+ CPPUNIT_ASSERT_EQUAL( OUString("ber"), a->suggestAutoCompletion() );
+
+ a->goBack();
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlagnummer12"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlag"), 15 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->insert( OUString("vorschlag13"), 13 );
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->gotoNode( "vorsch" );
+ CPPUNIT_ASSERT_EQUAL( OUString("lag"), a->suggestAutoCompletion() );
+
+ a->advance( 'l' );
+ CPPUNIT_ASSERT_EQUAL( OUString("ag"), a->suggestAutoCompletion() );
+
+ a->advance( 'a' );
+ CPPUNIT_ASSERT_EQUAL( OUString("g13"), a->suggestAutoCompletion() );
+
+ a->advance( 'g' );
+ CPPUNIT_ASSERT_EQUAL( OUString("13"), a->suggestAutoCompletion() );
+
+ a->advance( '1' );
+ CPPUNIT_ASSERT_EQUAL( OUString("3"), a->suggestAutoCompletion() );
+
+ a->advance( '3' );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->goBack();
+ a->advance( 'z' );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->gotoNode( "vorschlag13" );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->advance( 'g' );
+ a->advance( '1' );
+ a->advance( '3' );
+ a->remove( "vorschlag13" );
+ CPPUNIT_ASSERT_EQUAL( OUString(""), a->suggestAutoCompletion() );
+
+ a->insert( "VeraHatMichL1eb.", 1000000 );
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("VeraHatMichL1eb."), a->suggestAutoCompletion() );
+
+ a->gotoNode( "VeraHatMich" );
+ a->remove( "VeraHatMichL1eb." );
+ CPPUNIT_ASSERT_EQUAL( OUString(""), a->suggestAutoCompletion() );
+
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("vorschlag"), a->suggestAutoCompletion() );
+
+ a->gotoNode( "VeraLiebtMich" );
+ a->insert( 600 );
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("VeraLiebtMich"), a->suggestAutoCompletion() );
+
+ a->insert( "VeraHatMichL1eb.", 1000000 );
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("VeraHatMichL1eb."), a->suggestAutoCompletion() );
+
+ a->gotoNode( "VeraHatMich" );
+ a->remove( "VeraHatMichL1eb." );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->advance( 'L' );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->insert( "VeraHatMichL1eb.", 1000000 );
+ a->returnToRoot();
+ a->gotoNode( "VeraHatMich" );
+ a->remove( "VeraHatMichL1eb." );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->goBack();
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->insert( "VeraHatMichL1eb.", 1000000 );
+ a->returnToRoot();
+ a->gotoNode( "VeraHatMich" );
+ a->remove( "VeraHatMichL1eb." );
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->goBack();
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->insert( "neu", 2000 );
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("neu"), a->suggestAutoCompletion() );
+
+ a->gotoNode( "ne" );
+ CPPUNIT_ASSERT_EQUAL( OUString("u"), a->suggestAutoCompletion() );
+
+ a->advance( sal_Unicode('u') );
+ a->advance( sal_Unicode('e') );
+ a->advance( sal_Unicode('r') );
+ a->insert();
+ CPPUNIT_ASSERT ( a->suggestAutoCompletion().isEmpty() );
+
+ a->returnToRoot();
+ CPPUNIT_ASSERT_EQUAL( OUString("neu"), a->suggestAutoCompletion() );
+
+ a->advance( 'n' );
+ CPPUNIT_ASSERT_EQUAL( OUString("eu"), a->suggestAutoCompletion() );
+
+ a->advance( 'e' );
+ CPPUNIT_ASSERT_EQUAL( OUString("uer"), a->suggestAutoCompletion() );
+
+ // Test unicode
+ OUString aQueryString = rtl::OStringToOUString( "H\xC3\xA4llo", RTL_TEXTENCODING_UTF8 );
+ a->insert( aQueryString );
+ a->returnToRoot();
+ a->advance( sal_Unicode('H') );
+
+ OUString aAutocompletedString = a->suggestAutoCompletion();
+ OUString aExpectedString = rtl::OStringToOUString( "\xC3\xA4llo", RTL_TEXTENCODING_UTF8 );
+
+ CPPUNIT_ASSERT_EQUAL( aExpectedString, aAutocompletedString );
+
+ OString aUtf8String( "\xe3\x81\x82\xe3\x81\x97\xe3\x81\x9f" );
+ aQueryString = rtl::OStringToOUString( aUtf8String, RTL_TEXTENCODING_UTF8 );
+ a->insert( aQueryString );
+
+ OUString aGotoString = rtl::OStringToOUString( "\xe3\x81\x82", RTL_TEXTENCODING_UTF8 );
+ a->gotoNode( aGotoString );
+
+ aAutocompletedString = a->suggestAutoCompletion();
+ aExpectedString = rtl::OStringToOUString( "\xe3\x81\x97\xe3\x81\x9f", RTL_TEXTENCODING_UTF8 );
+ CPPUNIT_ASSERT_EQUAL( aExpectedString, aAutocompletedString );
+
+ delete a;
+}
+
+} // namespace end
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/lookuptree/LatinLookupTree.cxx b/editeng/source/lookuptree/LatinLookupTree.cxx
new file mode 100644
index 000000000000..5d78724c33b8
--- /dev/null
+++ b/editeng/source/lookuptree/LatinLookupTree.cxx
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/LatinLookupTree.hxx>
+#include <editeng/LatinTreeNode.hxx>
+
+LatinLookupTree::LatinLookupTree(OUString sLanguage) :
+ LookupTree( sLanguage )
+{
+ for ( sal_Unicode i = 0; i < 52; ++i )
+ {
+ m_pLeaves[i] = NULL;
+ }
+}
+
+LatinLookupTree::~LatinLookupTree()
+{
+ freeMemory();
+}
+
+void LatinLookupTree::returnToRoot()
+{
+ if ( m_pCurrent == m_pHead )
+ return;
+
+ // If there is no entry in this node or the tree that sprouts from it.
+ if ( m_pCurrent &&
+ m_pCurrent->m_pParent &&
+ !m_pCurrent->m_nChildren &&
+ !m_pCurrent->m_nKeyProbability )
+ {
+ m_pCurrent->m_pParent->childHasChanged( m_pCurrent, 0, true );
+ }
+
+ m_pCurrent = m_pHead;
+}
+
+void LatinLookupTree::gotoNode(OUString sNode)
+{
+ returnToRoot();
+
+ // walk down the tree...
+ for ( int i = 0; i < sNode.getLength(); i++ )
+ {
+ m_pCurrent = m_pCurrent->advanceKey( sNode[i] );
+ }
+}
+
+void LatinLookupTree::advance(const sal_Unicode cKey)
+{
+ m_pCurrent = m_pCurrent->advanceKey( cKey );
+}
+
+void LatinLookupTree::goBack()
+{
+ if ( m_pCurrent->m_pParent ) // if we're not at the root
+ {
+ const Node* const pChild = m_pCurrent;
+ m_pCurrent = m_pCurrent->m_pParent; // set focus to parent
+
+ // if this is an unused tree leaf
+ if ( !pChild->m_nChildren && !pChild->m_nKeyProbability )
+ {
+ m_pCurrent->removeChild( m_pCurrent->getChildRef( pChild->m_cKey ) );
+ }
+ }
+}
+
+void LatinLookupTree::insert(OUString sKey, const int nProbability)
+{
+ if ( !sKey.isEmpty() && nProbability > 0 )
+ {
+ insertKey( sKey, nProbability );
+ }
+}
+
+void LatinLookupTree::insert(const int nProbability)
+{
+ if ( m_pCurrent == this )
+ return;
+
+ // change probability
+ int proba = m_pCurrent->m_nKeyProbability += nProbability;
+
+ // inform his parent
+ m_pCurrent->m_pParent->childHasChanged( m_pCurrent, proba );
+}
+
+void LatinLookupTree::remove(OUString sKey)
+{
+ if ( !sKey.isEmpty() )
+ {
+ removeKey( sKey );
+ }
+}
+
+OUString LatinLookupTree::suggestAutoCompletion() const
+{
+ if ( !m_pCurrent )
+ return OUString();
+
+ Node* pWalker = m_pCurrent;
+
+ int distance = 0, nTargetProbability = 0;
+ OUString sSuggestion;
+
+ while ( pWalker->m_pSuggest && ( distance < 2 ||
+ // Make sure the suggestion is at least 2 chars long.
+ nTargetProbability == pWalker->m_nHighestProbaInSubtree ) )
+ {
+ if ( distance < 2 )
+ nTargetProbability = pWalker->m_nHighestProbaInSubtree;
+
+ // follow the tree along the suggested route
+ pWalker = pWalker->m_pSuggest;
+ ++distance;
+ sSuggestion += OUString(pWalker->m_cKey);
+ }
+
+ return sSuggestion;
+}
+
+void LatinLookupTree::clear()
+{
+ freeMemory();
+}
+
+bool LatinLookupTree::isSeparatedlyHandled(const sal_Unicode cKey) const
+{
+ return
+ ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') )
+ || ( cKey >= sal_Unicode('A') && cKey <= sal_Unicode('Z') );
+}
+
+Node*& LatinLookupTree::getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder)
+{
+ int pos = -1;
+
+ // determine position in array if possible
+ if ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') )
+ {
+ pos = cKey - our_nLowerCaseA;
+ }
+ else if ( cKey >= sal_Unicode('A') && cKey <= sal_Unicode('Z') )
+ {
+ pos = cKey - our_nUpperCaseA + 26;
+ }
+
+ if ( pos != -1 )
+ {
+ return m_pLeaves[pos];
+ }
+ else
+ {
+ for ( std::list<Node*>::iterator i = m_lChildren.begin(); i != m_lChildren.end(); ++i )
+ {
+ if ( (*i)->m_cKey == cKey )
+ {
+ return *i;
+ }
+ }
+ if ( bCreatePlaceholder )
+ {
+ // Create new entry in case there isn't one.
+ m_lChildren.push_back( NULL );
+ return *(--m_lChildren.end());
+ }
+ else
+ {
+ return our_pNodeNullPointer;
+ }
+ }
+}
+
+void LatinLookupTree::evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const
+{
+ for ( sal_Unicode i = 0; i < 52; ++i )
+ {
+ if ( m_pLeaves[i] )
+ {
+ if ( m_pLeaves[i]->m_nHighestProbaInSubtree > nSuggest )
+ {
+ nSuggest = m_pLeaves[i]->m_nHighestProbaInSubtree;
+ pSuggest = m_pLeaves[i];
+ }
+ if ( m_pLeaves[i]->m_nKeyProbability > nSuggest )
+ {
+ nSuggest = m_pLeaves[i]->m_nKeyProbability;
+ pSuggest = m_pLeaves[i];
+ }
+ }
+ }
+}
+
+void LatinLookupTree::freeMemory()
+{
+ // remove nodes from array
+ for ( sal_Unicode i = 0; i < 52; ++i )
+ {
+ if ( m_pLeaves[i] )
+ {
+ m_pLeaves[i]->freeMemory();
+ delete m_pLeaves[i];
+ m_pLeaves[i] = NULL;
+ }
+ }
+ // clear list
+ while ( m_lChildren.size() )
+ {
+ Node* pTmp = m_lChildren.front();
+ m_lChildren.pop_front();
+ delete pTmp;
+ }
+}
+
+Node* LatinLookupTree::newNode(Node* pParent, const sal_Unicode cKey, const int nProbability)
+{
+ return new LatinTreeNode( this, pParent, cKey, nProbability );
+}
+
+const unsigned int LatinLookupTree::our_nLowerCaseA = 97;
+const unsigned int LatinLookupTree::our_nUpperCaseA = 65;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/lookuptree/LatinTreeNode.cxx b/editeng/source/lookuptree/LatinTreeNode.cxx
new file mode 100644
index 000000000000..b68e039d1349
--- /dev/null
+++ b/editeng/source/lookuptree/LatinTreeNode.cxx
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/LatinTreeNode.hxx>
+#include <editeng/LatinLookupTree.hxx>
+
+LatinTreeNode::LatinTreeNode(TreeHead* pHead, Node* pParent, const sal_Unicode cKey, const int nProbability) :
+ Node( pHead, pParent, cKey, nProbability )
+{
+ for ( sal_Unicode i = 0; i < 26; ++i )
+ {
+ m_pLeaves[i] = NULL;
+ }
+}
+
+LatinTreeNode::~LatinTreeNode()
+{
+ freeMemory();
+}
+
+bool LatinTreeNode::isSeparatedlyHandled(const sal_Unicode cKey) const
+{
+ return ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') );
+}
+
+Node*& LatinTreeNode::getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder)
+{
+ // determine position in array if possible
+ if ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') )
+ {
+ return m_pLeaves[cKey - LatinLookupTree::our_nLowerCaseA];
+ }
+ else
+ {
+ for ( std::list<Node*>::iterator i = m_lChildren.begin(); i != m_lChildren.end(); ++i )
+ {
+ if ( (*i)->m_cKey == cKey )
+ {
+ return *i;
+ }
+ }
+ if ( bCreatePlaceholder )
+ {
+ // Create new entry in case there isn't one.
+ m_lChildren.push_back( NULL );
+ return *(--m_lChildren.end());
+ }
+ else
+ {
+ return our_pNodeNullPointer;
+ }
+ }
+}
+
+void LatinTreeNode::evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const
+{
+ for ( sal_Unicode i = 0; i < 26; ++i )
+ {
+ if ( m_pLeaves[i] )
+ {
+ if ( m_pLeaves[i]->m_nHighestProbaInSubtree > nSuggest )
+ {
+ nSuggest = m_pLeaves[i]->m_nHighestProbaInSubtree;
+ pSuggest = m_pLeaves[i];
+ }
+ if ( m_pLeaves[i]->m_nKeyProbability > nSuggest )
+ {
+ nSuggest = m_pLeaves[i]->m_nKeyProbability;
+ pSuggest = m_pLeaves[i];
+ }
+ }
+ }
+}
+
+void LatinTreeNode::freeMemory()
+{
+ // remove nodes from array
+ for ( sal_Unicode i = 0; i < 26; ++i )
+ {
+ if ( m_pLeaves[i] )
+ {
+ m_pLeaves[i]->freeMemory();
+ delete m_pLeaves[i];
+ m_pLeaves[i] = NULL;
+ }
+ }
+ // clear list
+ while ( m_lChildren.size() )
+ {
+ Node* pTmp = m_lChildren.front();
+ m_lChildren.pop_front();
+ delete pTmp;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/editeng/source/lookuptree/Node.cxx b/editeng/source/lookuptree/Node.cxx
new file mode 100644
index 000000000000..6d5e32050785
--- /dev/null
+++ b/editeng/source/lookuptree/Node.cxx
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <editeng/TreeHead.hxx>
+#include <editeng/Node.hxx>
+
+Node::Node(TreeHead* const pHead, Node* const pParent,
+ const sal_Unicode cKey, const int nProbability ) :
+ m_cKey( cKey ),
+ m_nKeyProbability( nProbability ),
+ m_nHighestProbaInSubtree( 0 ),
+ m_pParent( pParent ),
+ m_pSuggest( NULL ),
+ m_pHead( pHead ),
+ m_nChildren( 0 )
+{
+}
+
+Node::~Node()
+{
+}
+
+void Node::removeChild(Node*& pChild)
+{
+ const sal_Unicode cKey = pChild->m_cKey;
+
+ if ( pChild )
+ {
+ delete pChild;
+ pChild = NULL;
+ --m_nChildren;
+ }
+
+ if ( !isSeparatedlyHandled( cKey ) )
+ {
+ std::list<Node*>::iterator i = m_lChildren.begin();
+ while ( i != m_lChildren.end() )
+ {
+ if ( !(*i) )
+ {
+ i = m_lChildren.erase( i );
+ }
+ ++i;
+ }
+ }
+}
+
+void Node::insertKey(OUString sKey, const int nProbability)
+{
+ if ( !sKey.isEmpty() )
+ {
+ const sal_Unicode cKey = sKey[0];
+ sKey = sKey.copy( 1 );
+
+ Node*& pChild = getChildRef( cKey, true );
+
+ if ( !pChild )
+ {
+ pChild = m_pHead->newNode( this, cKey );
+ ++m_nChildren;
+ }
+
+ pChild->insertKey( sKey, nProbability );
+ }
+ else
+ {
+ m_nKeyProbability += nProbability;
+ if ( m_pParent )
+ {
+ // inform parent about change
+ int probability = m_nHighestProbaInSubtree > m_nKeyProbability ? m_nHighestProbaInSubtree : m_nKeyProbability;
+ m_pParent->childHasChanged( this, probability);
+ }
+ }
+}
+
+// Removes a complete keyword starting from this node of the tree.
+void Node::removeKey(OUString sKey)
+{
+ if ( !sKey.isEmpty() )
+ {
+ Node*& pChild = getChildRef( sKey[0] );
+
+ if ( pChild )
+ {
+ // recursive call downwards
+ pChild->removeKey( sKey.copy( 1 ) );
+ }
+ // Else: Keyword to be removed couldn't be found within the tree.
+ // No further changes are going to be made.
+ }
+ else // If we are the node to be removed...
+ {
+ // ... remove our entry from tree...
+ m_nKeyProbability = 0;
+ // ... and make sure our parent is updated.
+ m_pParent->childHasChanged( this, m_nHighestProbaInSubtree, this != m_pHead->m_pCurrent );
+ }
+}
+
+Node *Node::advanceKey(const sal_Unicode cKey)
+{
+ Node*& pChild = getChildRef( cKey, true );
+
+ if ( !pChild )
+ {
+ pChild = m_pHead->newNode( this, cKey );
+ }
+
+ return pChild;
+}
+
+void Node::childHasChanged(Node *pChild, const int nProbability, bool bAllowRemoval)
+{
+ if ( nProbability > m_nHighestProbaInSubtree )
+ {
+ m_pSuggest = pChild;
+ m_nHighestProbaInSubtree = nProbability;
+
+ if ( m_pParent ) // recursive call upwards
+ {
+ int probabilityChange = nProbability > m_nKeyProbability ? nProbability : m_nKeyProbability;
+ m_pParent->childHasChanged( this, probabilityChange );
+ }
+ }
+ else if ( !nProbability || nProbability < m_nHighestProbaInSubtree )
+ {
+ bool bNewEvaluationRequired = m_pSuggest == pChild;
+
+ if ( !nProbability && bAllowRemoval )
+ {
+ // Remove child. Caller needs to make sure we are allowed to.
+ removeChild( getChildRef( pChild->m_cKey ) );
+ }
+
+ if ( bNewEvaluationRequired )
+ {
+ // This is used to store whether we need to inform our parent about
+ // the changes within this node.
+ bool bNodeProbabilityChanged;
+
+ reevaluateSuggestion( bNodeProbabilityChanged );
+
+ // If necessary, inform our parent about change via recursive call
+ if ( bNodeProbabilityChanged && m_pParent )
+ {
+ bAllowRemoval = bAllowRemoval && this != m_pHead->m_pCurrent;
+ int probabilityChange = m_nHighestProbaInSubtree > m_nKeyProbability ? m_nHighestProbaInSubtree : m_nKeyProbability;
+ m_pParent->childHasChanged( this, probabilityChange, bAllowRemoval );
+ }
+ }
+ }
+}
+
+void Node::reevaluateSuggestion(bool& bNodeProbabilityChanged)
+{
+ if ( m_nChildren ) // find child with highest probability
+ {
+ int nSuggest = 0;
+ Node* pSuggest = NULL;
+
+ // find child with highest probability in array
+ evaluateSeparateStorage( nSuggest, pSuggest );
+
+ // do the same thing within list
+ for ( std::list<Node*>::iterator i = m_lChildren.begin(); i != m_lChildren.end(); ++i )
+ {
+ if ( (*i)->m_nHighestProbaInSubtree > nSuggest )
+ {
+ nSuggest = (*i)->m_nHighestProbaInSubtree;
+ pSuggest = (*i);
+ }
+ if ( (*i)->m_nKeyProbability > nSuggest )
+ {
+ nSuggest = (*i)->m_nKeyProbability;
+ pSuggest = (*i);
+ }
+ }
+
+ // determine whether we need to inform our parent
+ bNodeProbabilityChanged = m_nHighestProbaInSubtree != nSuggest;
+
+ m_pSuggest = pSuggest;
+ m_nHighestProbaInSubtree = nSuggest;
+ }
+ else // there are no children
+ {
+ m_pSuggest = NULL;
+ m_nHighestProbaInSubtree = 0;
+
+ bNodeProbabilityChanged = true;
+ }
+}
+
+Node* Node::our_pNodeNullPointer = NULL;
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */