http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/asdocgen.bat
----------------------------------------------------------------------
diff --git a/Squiggly/main/SpellingFramework/asdocgen.bat 
b/Squiggly/main/SpellingFramework/asdocgen.bat
new file mode 100644
index 0000000..b458486
--- /dev/null
+++ b/Squiggly/main/SpellingFramework/asdocgen.bat
@@ -0,0 +1,18 @@
+@echo off
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements.  See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License.  You may obtain a copy of the License at
+rem
+rem     http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+REM This generates the ASDoc for Engine and SInC. Modify the path as you need. 
TODO: move to build folder.
+"C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.0.0\bin\asdoc" 
-source-path src -doc-classes 
com.adobe.linguistics.spelling.framework.ResourceConfig 
com.adobe.linguistics.spelling.framework.SpellingConfiguration 
com.adobe.linguistics.spelling.framework.SpellingService 
com.adobe.linguistics.spelling.framework.UserDictionary -library-path 
"C:\Program Files\Adobe\Adobe Flash Builder 4\sdks\4.0.0\frameworks\libs" 
-exclude-dependencies=true -output docs -main-title "AdobeSpellingFramework API 
Documentation 0.4" -package com.adobe.linguistics.spelling.framework "This 
package provides spell checking framework for easy integration with the 
Squiggly spelling engine."

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ResourceTable.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ResourceTable.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ResourceTable.as
new file mode 100644
index 0000000..a72a95d
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ResourceTable.as
@@ -0,0 +1,134 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+  
+package com.adobe.linguistics.spelling.framework
+{
+       import flash.utils.IDataInput;
+       import flash.utils.IDataOutput;
+       import flash.utils.IExternalizable;
+       
+       
[RemoteClass(alias='com.adobe.linguistics.spelling.framework.ResourceConfig')]
+               
+       /**
+        * The ResourceTable class contains a table mapping language to the 
spelling resources. Resources here imply the URL of rule file and dict file to 
be used for the language.
+        * 
+        * @includeExample 
../Examples/Flex/ConfigExample/src/ConfigExample.mxml -noswf
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       public class ResourceTable implements IExternalizable
+       {
+               private var _resources:Object;
+               
+               /**
+                * Constructs a new ResourceTable object that performs language 
to resource mapping. 
+                */
+               public function ResourceTable()
+               {
+                       _resources = new Object();
+               }
+
+               /**
+                * A list of languages supported in this ResourceTable
+                */
+               public function get availableLanguages():Vector.<String>
+               {
+                       var result:Vector.<String> = new Vector.<String>();
+                       for (var i:String in _resources)
+                       {
+                               result.push(i);
+                       }
+                       return result;
+               }
+               
+               /**
+                * Set the resource for the specified language.
+                * 
+                * @param language The language that you want to assign 
spelling resources to.
+                * @param resource A <code>Object</code> that behave as an 
associated array, it 
+                * contains the path(s) to the resource file(s). For the time 
being, the only 
+                * supported resource is hunspell dictionary, which contains a 
rule file (.aff) and a 
+                * dictionary file (.dic). 
+                * 
+                * @example The following code sets the resource for American 
English language.
+                * <listing version="3.0">
+                * var resourceTable:ResourceTable = new ResourceTable();
+                * resourceTable.setResource("en_US", {rule:"en_US.aff", 
dict:"en_US.dic"});
+                * </listing>
+                */
+               public function setResource(language:String, 
resource:Object):void
+               {
+                       _resources[language] = resource;
+               }
+               
+               /**
+                * Get the resource for the specified language.
+                * 
+                * @param language The language associated with the resource 
you are looking for.
+                * @return An <code>Object</code> that stores the resource file 
URL(s).
+                * @example The following code gets and uses the resource for 
American English language.
+                * <listing version="3.0">
+                * var resource_en_US:Object = 
SpellingConfiguration.resourceTable.getResource("en_US");
+                * trace("rule file:" + resource_en_US["rule"] + ", dictionary 
file:" + resource_en_US.dict);
+                * </listing>
+                */
+               public function getResource(language:String):Object
+               {
+                       return _resources[language];
+               }
+               
+               /**
+                * Overwrite toString() for debug purpose.
+                * @private
+                */
+               public function toString():String
+               {
+                       var result:String = new String();
+                       for (var i:String in _resources)
+                       {
+                               result += i;
+                               result += ": ";
+                               result += "[";
+                               for (var j:String in getResource(i))
+                               {
+                                       result += j + ":" + getResource(i)[j] + 
" "
+                               }
+                               result += "]";
+                               result += "; ";
+                       }
+                       return result;
+               }
+               
+               /**
+                * Implement this IExternalizable API so that it can be 
serialized to an ByteArray.
+                * @private
+                */
+               public function readExternal(input:IDataInput):void {
+                       _resources = input.readObject();
+               }
+               
+               /**
+                * Implement this IExternalizable API so that it can be 
serialized to an ByteArray.
+                * @private
+                */
+               public function writeExternal(output:IDataOutput):void {
+                       output.writeObject(_resources);
+               }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingConfiguration.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingConfiguration.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingConfiguration.as
new file mode 100644
index 0000000..38f316a
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingConfiguration.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+  
+  
+package com.adobe.linguistics.spelling.framework
+{
+       
+       
+       import flash.errors.IllegalOperationError;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+       import com.adobe.linguistics.spelling.framework.ResourceTable;
+       
+       /**
+        * The SpellingConfiguration is for setting and getting the 
configuration for the spell checker.
+        * 
+        * @includeExample 
../Examples/Flex/ConfigExample/src/ConfigExample.mxml -noswf
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       
+       public class SpellingConfiguration
+       {
+               
+
+               private static var _resourceTable:ResourceTable = null;
+               private static var 
_enableDictionarySplit:Boolean=false;//static value so can be initialised here
+               private static var 
_wordsPerDictionarySplit:int=InternalConstants.WORDS_PER_SPLIT;
+               
+               /**
+                * The resourceTable is used for mapping the language to 
resources.
+                */
+               public static function get resourceTable():ResourceTable
+               {
+                       // Lazy initialization for the default value
+                       if (_resourceTable == null) {
+                               _resourceTable = new ResourceTable();
+                               //_resourceTable.setResource("en_US", 
{rule:"data/en_US.aff", dict:"data/en_US.dic"});
+                       }
+                       return _resourceTable;  
+               }
+               
+               public static function set 
resourceTable(resourceTable:ResourceTable):void
+               {
+                       _resourceTable = resourceTable;
+               }
+               
+               /**
+                * This is a flag that enables/disables loading of dictionary 
in splits.
+                * By default this flag is set to <code>false</code>. In case 
the initial loading time of dictionaries is found slow, this flag should be set 
to <code>true</code>. By enabling this, squiggly will load dictionary in splits 
with each split having <code>wordsPerDictionarySplit</code> number of words.
+                * <p>NOTE: This property, if used, should be set before 
calling <code>SpellUI.enableSpeliing</code>. Once 
<code>SpellUI.enableSpeliing</code> is called dictionaries will be loaded 
according to default values, and this property will not be used. </p>
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public static function get enableDictionarySplit():Boolean
+               {
+                       return _enableDictionarySplit;  
+               }
+               
+               public static function set 
enableDictionarySplit(enableDictionarySplit:Boolean):void
+               {
+                       _enableDictionarySplit = enableDictionarySplit;
+               }
+               
+               /**
+                * This property defines the number of words in one dictionary 
split.
+                * By default the value of this property is set to 20000 words. 
This property is used only if <code>enableDictionarySplit</code> is set to 
<code>true</code>. If <code>enableDictionarySplit</code> is set to 
<code>flase</code> this property turns void.
+                * <p>NOTE: This property, if used, should be defined before 
calling <code>SpellUI.enableSpeliing</code>. Once 
<code>SpellUI.enableSpeliing</code> is called dictionaries will be loaded 
according to default values, and this property will not be used.</p>
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public static function get wordsPerDictionarySplit():int
+               {
+                       
+                       return _wordsPerDictionarySplit;        
+               }
+               
+               public static function set 
wordsPerDictionarySplit(wordsPerDictionarySplit:int):void
+               {
+                       if(wordsPerDictionarySplit<=0){
+                               //Do error Handling
+                               throw new 
IllegalOperationError("wordsPerDictionarySplit should be a positive non-zero 
value.");
+                       }
+                       _wordsPerDictionarySplit = wordsPerDictionarySplit;
+               }
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
new file mode 100644
index 0000000..9e687ee
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
@@ -0,0 +1,241 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+  
+  
+package com.adobe.linguistics.spelling.framework
+{
+       import com.adobe.linguistics.spelling.HunspellDictionary;
+       import com.adobe.linguistics.spelling.SpellChecker;
+       import com.adobe.linguistics.spelling.UserDictionary;
+       import com.adobe.linguistics.spelling.core.UserDictionaryEngine;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+       
+       import flash.events.Event;
+       import flash.events.EventDispatcher;
+//     import flash.utils.Timer;
+//     import flash.events.TimerEvent;
+       
+       /**
+        * The SpellingService provides spell checking features for the 
specified language. 
+        * This class makes use of SpellingConfiguration class to dynamically 
get the language dictionary location. The dictionaries are then loaded and 
SpellChecker object
+        * created based on these dictionaries. SpellingService also caches 
SpellChecker and dictionary objects for individual languages for efficient 
reuse.
+        * @includeExample 
../Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml -noswf
+        * @playerversion Flash 10
+        * @langversion 3.0.
+        * 
+        */
+       public class SpellingService extends EventDispatcher
+       {
+               private var _language:String = null;
+               private var _engine:SpellChecker = null;
+               private var _udEngine:UserDictionaryEngine = null;
+               private var _userDictionaries:Array = new Array();
+               
+                               
+               // Static table for caching engines and fixed dictionaries
+               private static var _engines:Array = new Array();
+               private static var _dicts:Array = new Array();
+               
+               /**
+                * Constructs a spelling service object.
+                *
+                * @param language The language used to create a 
<code>SpellingService</code>.
+                */
+               public function SpellingService(language:String)
+               {
+                       _language = language;           
+               }
+
+               /**
+                * Initialize the <code>SpellingService</code>. Once the 
initialization is done, an <code>Event.COMPLETE</code> event will be dispatched
+                * and the <code>SpellingService</code> is ready to be used.
+                */             
+               public function init():void
+               {
+                       _udEngine = new UserDictionaryEngine();
+                       
+                       // Since the engine and dictionary are shared, the 
loading has three status
+                       // Loaded
+                       if (_engines[_language] != null)
+                       {
+                               loadDictComplete(null);
+                       }
+                       // Loading
+                       else if (_dicts[_language] != null)
+                       {
+                               
_dicts[_language].addEventListener(Event.COMPLETE, loadDictComplete);
+                       }
+                       // Loading not started
+                       else
+                       {                       
+                               var urls:Object = 
SpellingConfiguration.resourceTable.getResource(_language);
+                               var hunspellDict:HunspellDictionary = new 
HunspellDictionary();
+                               _dicts[_language] = hunspellDict;
+                               hunspellDict.addEventListener(Event.COMPLETE, 
loadDictComplete);
+                               /*added for check on 10-12-2010
+                               var mytimer:Timer =new Timer(50,0);
+                               mytimer.start();
+                               var initTime:int =mytimer.currentCount;
+                               trace(initTime);*/
+                               
+                               //adding code for enabling loading in parts. 
Since spelling service class needs SpellingConfiguration so it this property 
uses it.
+                               
hunspellDict.enableDictionarySplit=SpellingConfiguration.enableDictionarySplit;//user
 has to be freed from this. So we have to put a default value in 
SpellingConfiguration class.
+                               
hunspellDict.wordsPerDictionarySplit=SpellingConfiguration.wordsPerDictionarySplit;//user
 has to be freed from this. So we have to put a default value in 
SpellingConfiguration class.
+                               
+                               hunspellDict.load(urls["rule"], urls["dict"]);
+                               /*var timePassed:int =mytimer.currentCount;
+                               trace(timePassed);*/
+                       }
+               }
+               
+               private function loadDictComplete(e:Event):void
+               {
+                       if (_engines[_language] == null) {
+                               _engines[_language] = new 
SpellChecker(_dicts[_language]);
+                       }
+                       _engine = _engines[_language];
+                       dispatchEvent(new Event(Event.COMPLETE));
+               }
+       
+               /**
+                * Check the spelling of a word.
+                *
+                * @param word The word to be checked.
+                * @return True if the word is correctly spelled, false if it 
is misspelled.
+                */             
+               public function checkWord(word:String):Boolean
+               {
+                       return ((_udEngine.spell(word)) || 
(_engine.checkWord(word)));
+               }
+
+               /**
+                * Get the suggestion of a misspelled word. 
+                *
+                * @param word The word to be checked.
+                * @return A vector containing all suggestions for the 
misspelled word, ordered by similarity to the original word. 
+                * Note that if a word is already correctly spelled, an empty 
Vector is returned.
+                * @internal TODO: get the suggestions from user dicitonaries
+                */                     
+               public function getSuggestions(word:String):Vector.<String>
+               {
+                       var resultArray:Array = _engine.getSuggestions(word);
+                       
+                       var resultVector:Vector.<String> = new 
Vector.<String>();
+                       for each (var i:String in resultArray) {
+                               resultVector.push(i);           
+                       }
+                       
+                       return resultVector;
+               }
+               
+               /** 
+                * Add a <code>UserDictionary</code> to the 
<code>SpellingService</code>.
+                * 
+                * @param userDictionary The UserDictionary to be added.
+                * @return True if the UserDictionary is added successfully, 
false if any error occurs. An example error scenario: Trying to add a 
previously added user dictionary. 
+                * @see UserDictionary
+                */
+               public function 
addUserDictionary(userDictionary:UserDictionary):Boolean
+               {
+                       if  
(_udEngine.addDictionary(userDictionary.internalUserDictionary) == true)
+                       {
+                               _userDictionaries.push(userDictionary);
+                               return true;
+                       } 
+                       
+                       return false;
+               }
+
+               /** 
+                * Remove a <code>UserDictionary</code> from the 
<code>SpellingService</code>.
+                * 
+                * @param userDictionary The UserDictionary to be removed.
+                * @return True if the UserDictionary is removed successfully, 
false if any error occurs. An example error scenario: Trying to remove a user 
dictionary that has not been added previously. 
+                * @see UserDictionary
+                */             
+               public function 
removeUserDictionary(userDictionary:UserDictionary):Boolean
+               {
+                       if 
(_udEngine.removeDictionary(userDictionary.internalUserDictionary) == true)
+                       {
+                               for ( var i:int =0; i < 
_userDictionaries.length; ++i ) {
+                                       if ( userDictionary == 
_userDictionaries[i] ) {
+                                               _userDictionaries.splice(i,1);
+                                               return true;
+                                       }
+                               }
+                       }
+                       
+                       return false;
+               }
+               
+               /**
+                * A <code>Vector</code> of user dictionaries added to this 
<code>SpellingService</code>.
+                * 
+                * @return A <code>Vector</code> of <code>UserDictionary</code> 
objects.
+                * @see UserDictionary
+                */
+               public function get userDictionaries():Vector.<UserDictionary>
+               {       
+                       var resultVector:Vector.<UserDictionary> = new 
Vector.<UserDictionary>;
+                       for each (var i:UserDictionary in _userDictionaries) {
+                               resultVector.push(i);           
+                       }
+                       
+                       return resultVector;
+               }
+               
+               /**
+                * This property controls if words in all upper-case should be 
considered as properly spelled or not.
+                * 
+                * <table class="innertable">
+                *              <tr>
+                *                      <td 
align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td>
+                *                      <td 
align="center"><strong>&#160;</strong></td>
+                *                      <td 
align="center"><strong>Description</strong></td>
+                *              </tr>
+                *              <tr>
+                *                      <td><code>false</code></td>
+                *                      <td>Default</td>
+                *                      <td><p>Words with all characters in 
upper case are checked against the dictionary for proper spelling.</p>
+                *                              <p>Example: if 
<code>ignoreWordWithAllUpperCase = false</code>, "MISPEL" will be checked for 
proper spelling.</p></td>
+                *              </tr>
+                *              <tr>
+                *                      <td><code>true</code></td>
+                *                      <td>&#160;</td>
+                *                      <td><p>Any words with all characters in 
upper case are always considered as properly spelled,
+                *                                      no matter whether the 
word is in the dictionary or not.</p>
+                *                              <p>Example: if 
<code>ignoreWordWithAllUpperCase = true</code>, "MISPEL" will be considered as 
properly spelled.</p></td>
+                *              </tr>
+                *      </table>
+                * */
+               /* Getter Function for ignoring all word with all upper case*/
+               public function get ignoreWordWithAllUpperCase():Boolean
+               {
+                       return _engine.ignoreWordWithAllUpperCase;
+               }
+               /* Setter Function for ignoring all word with all upper case*/
+               public function set 
ignoreWordWithAllUpperCase(value:Boolean):void
+               {
+                       _engine.ignoreWordWithAllUpperCase=value;
+               }
+               
+       }
+}
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloHighlighter.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloHighlighter.as
new file mode 100644
index 0000000..6945e20
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloHighlighter.as
@@ -0,0 +1,124 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import __AS3__.vec.Vector;
+       
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.geom.Point;
+       import flash.text.TextField;
+       
+       import mx.core.IUITextField;
+
+       /**
+        * <p>This class facilitates drawing of squiggly lines below words for 
TextField class. TextField class is used to create display objects for text 
display 
+        * and input for Halo TextArea and TextInput components. 
HaloHighlighter could therefore be used for drawing squiggly lines in these 
Halo components.</p>
+        *      
+        * @playerversion Flash 9.x
+        * @langversion 3.0
+        */
+
+       public class HaloHighlighter implements IHighlighter
+       {
+               private var mTextField:TextField;
+               private var mHighlighter:SpellingHighlighter;
+               /*
+               * offset point:
+               */
+               private var _offsetPoint:Point;
+
+               /**
+                * The constructor for HaloHighlighter.
+                * @param textField <code>TextField</code> in which to enable 
highlighting.              
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function HaloHighlighter( textField:TextField )
+               {
+                       if (textField == null ) throw new Error("illegal 
argument."); 
+                       mTextField = textField;
+                       mHighlighter = null;
+                       this._offsetPoint = new Point(0,0);
+               }
+               /**
+                * Draw squiggly lines below a given token.
+                * @param token <code>Token</code> information of the word to 
be highlighted.            
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function drawSquiggleAt(token:Token):void
+               {
+                       squiggleWord(token);
+               }
+               
+               /**
+                * Clear all squiggly lines in the TextField.           
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function clearSquiggles():void
+               {
+                       if (mHighlighter) {
+                               mTextField.parent.removeChild(mHighlighter);
+                               mHighlighter=null;
+                       }
+                       
+               }
+               
+               /**
+                * Set offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public function set offsetPoint(op:Point):void{
+                       _offsetPoint = op;
+               }
+               
+               /**
+                * Get offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public function get offsetPoint():Point{
+                       return _offsetPoint;
+               }
+               
+
+               private function squiggleWord(token:Token):void {
+                                               
+                       if (!mHighlighter) {
+                               mHighlighter= new SpellingHighlighter( 
mTextField as IUITextField);
+                               mTextField.parent.addChild(mHighlighter);       
                        
+                       }
+                                               
+                       mHighlighter.drawSquigglyLine(token.first, token.last);
+               
+               
+                       //mTextField.parent.addChild(mHighlighter);     
+                       mHighlighter.move(_offsetPoint.x, _offsetPoint.y);
+               }
+
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloWordProcessor.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloWordProcessor.as
new file mode 100644
index 0000000..cf77943
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/HaloWordProcessor.as
@@ -0,0 +1,111 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.ITokenizer;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.text.TextField;
+       import flash.text.TextFormat;
+       
+       import mx.controls.TextArea;
+       import mx.controls.TextInput;
+
+
+       public class HaloWordProcessor implements IWordProcessor
+       {
+               private var mTextField:TextField;
+
+               public function HaloWordProcessor(textField:TextField)
+               {
+                       if (textField == null ) throw new Error("illegal 
argument."); 
+                       mTextField = textField;
+               }
+                               
+               
+               public function replaceText(token:Token, 
replacement:String):void {
+                       var startIndex:int = token.first;
+                       var endIndex:int = token.last;
+                       
+                       if ( replacement == null ) return;
+                       
+                       if (mTextField.text.length<endIndex || startIndex<0) {
+                               return;
+                       }
+                       
+                       var _misspellStart:int = startIndex;
+                       var _misspellEnd:int = endIndex;
+                       // Try to preserve the format, this works if the whole 
misspelled word is the same format
+                       var tf:TextFormat = 
mTextField.getTextFormat(_misspellStart, _misspellEnd);
+                       mTextField.replaceText(_misspellStart, _misspellEnd, 
replacement);      
+                       mTextField.setTextFormat(tf, _misspellStart, 
_misspellStart+replacement.length);
+                       
+                       var ta:TextArea = mTextField.parent as TextArea;
+                       var ti:TextInput = mTextField.parent as TextInput;
+                       
+                       if (ta != null) {
+                               ta.selectionBeginIndex = _misspellStart + 
replacement.length;
+                               ta.selectionEndIndex = _misspellStart + 
replacement.length;
+                       }
+                       else if (ti != null) {
+                               ti.selectionBeginIndex = _misspellStart + 
replacement.length;
+                               ti.selectionEndIndex = _misspellStart + 
replacement.length;                             
+                       }
+                       else {
+                               // Do nothing if it's not a valid text component
+                       }
+               }
+
+               
+               public function getWordAtPoint(x:uint, y:uint, 
externalTokenizer:ITokenizer=null):Token
+               {
+                       var _token:Token = tryGetWordAtPoint(x,y, 
externalTokenizer);
+                       return _token;
+               }
+               
+               private function tryGetWordAtPoint(x:uint, y:uint, 
externalTokenizer:ITokenizer=null):Token {
+                       // TODO: use a better alternative than _misspellStart, 
end
+                       var index:uint = mTextField.getCharIndexAtPoint(x + 
mTextField.scrollH, y);
+                       if (index >= mTextField.text.length) return null;
+
+                       var tmpToken:Token = new Token(index,index);
+                       var tokenizer:ITokenizer;
+                       if ( externalTokenizer == null ) {
+                               tokenizer = new TextTokenizer(mTextField.text); 
+                       }else {
+                               tokenizer = externalTokenizer;
+                       }
+                       
+                       var result:Token = new Token(0,0);
+                       
+                       var preToken:Token = 
tokenizer.getPreviousToken(tmpToken);
+                       var nextToken:Token = tokenizer.getNextToken(tmpToken);
+                       if ( preToken.last == nextToken.first ) {
+                               result.first = preToken.first;
+                               result.last = nextToken.last;
+                               return result;          
+                       }else {
+                               return null;
+                       }
+               }
+
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
new file mode 100644
index 0000000..a8b826f
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.Token;
+       import __AS3__.vec.Vector;
+       import flash.geom.Point;
+       
+       public interface IHighlighter
+       {
+               function drawSquiggleAt(token:Token):void;
+               function clearSquiggles():void;
+               function set offsetPoint(op:Point):void;
+               function get offsetPoint():Point;
+               
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
new file mode 100644
index 0000000..76c3c8e
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
@@ -0,0 +1,30 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.ITokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       public interface IWordProcessor
+       {
+               function getWordAtPoint(x:uint, y:uint, 
externalTokenizer:ITokenizer=null):Token;
+               function replaceText(token:Token, replacement:String):void;
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkHighlighter.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkHighlighter.as
new file mode 100644
index 0000000..fc5308d
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkHighlighter.as
@@ -0,0 +1,225 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.Token;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import flash.geom.Point;
+       
+       import flash.display.Shape;
+       import flash.geom.Rectangle;
+       import flash.text.engine.TextLine;
+       
+       import flashx.textLayout.compose.TextFlowLine;
+       import flashx.textLayout.edit.SelectionManager;
+       import flashx.textLayout.elements.TextFlow;
+       import flashx.textLayout.tlf_internal;
+       
+       import spark.components.RichEditableText;
+       use namespace tlf_internal;     
+       
+       /**
+        * <p>This class facilitates drawing of squiggly lines below words for 
RichEditableText class. RichEditableText is a low-level UIComponent for 
displaying, 
+        * scrolling, selecting, and editing richly-formatted text. This class 
is used in the skins of the Spark versions of TextInput and TextArea. 
+        * SparkHighlighter could therefore be used for drawing squiggly lines 
in these Spark components.</p>
+        *      
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       public class SparkHighlighter implements IHighlighter
+       {
+               
+               private var mTextField:RichEditableText;
+               private var mHighlighter:Shape;
+               /*
+               * offset point:
+               */
+               private var _offsetPoint:Point;
+
+               /**
+                * The constructor for SparkHighlighter.
+                * @param richEditableText <code>RichEditableText</code> in 
which to enable highlighting.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function SparkHighlighter( 
richEditableText:RichEditableText )
+               {
+                       if (richEditableText == null ) throw new Error("illegal 
argument."); 
+                       mTextField = richEditableText;
+                       mHighlighter = null;
+                       this._offsetPoint = new Point(0,0);
+               }
+
+               /**
+                * Draw squiggly lines below a given token.
+                * @param token <code>Token</code> information of the word to 
be highlighted.            
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function drawSquiggleAt(token:Token):void
+               {
+                       squiggleWord(token);
+               }
+               
+               /**
+                * Clear all squiggly lines in the component.           
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function clearSquiggles():void
+               {
+                       if (mHighlighter) {
+                               mTextField.removeChild(mHighlighter);
+                               mHighlighter=null;
+                       }               
+               }
+               
+               /**
+                * Set offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public function set offsetPoint(op:Point):void{
+                       _offsetPoint = op;
+               }
+               
+               /**
+                * Get offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public function get offsetPoint():Point{
+                       return _offsetPoint;
+               }
+
+               
+
+               // TODO: refactor this code to share with halo components, and 
support words that cross lines
+               private function squiggleWord(token:Token):void {
+                                       
+                       var ta:RichEditableText = mTextField;
+                       if (!ta) return;                
+                       
+                       if (!mHighlighter) {
+                               mHighlighter= new Shape();
+                               mHighlighter.graphics.clear();
+                               mTextField.addChild(mHighlighter);      
+                       }
+                                       
+                       drawSquigglyLineForRange(token.first, token.last);
+                       
+                       // Just adjust the left padding, top padding is not an 
issue 
+                       //var pleft:uint = mTextField.getStyle("paddingLeft");
+                       //mHighlighter.x += pleft;              
+               }
+               
+               // Draw squiggly line
+               private function drawSquigglyLineForRange(start:Number, 
end:Number):void
+               {
+                       // draw squiggly line
+                       var tf:TextFlow = mTextField.textFlow;
+                       var tflFirst:TextFlowLine = 
tf.flowComposer.findLineAtPosition(start);
+                       var tflLast:TextFlowLine = 
tf.flowComposer.findLineAtPosition(end);
+                       var tflIndexFirst:int = 
tf.flowComposer.findLineIndexAtPosition(start);
+                       var tflIndexLast:int = 
tf.flowComposer.findLineIndexAtPosition(end);
+                       
+                       // Pointer
+                       var tflIndex:int = tflIndexFirst;
+                       var tfl:TextFlowLine = tflFirst;
+                       
+                       if (tflIndexFirst == tflIndexLast) {
+                               // Draw one line
+                               drawSquigglyLineAtIndex(tflIndexFirst, start - 
tflFirst.absoluteStart, end - tflFirst.absoluteStart);
+                       } else {
+                               // Multiple lines (very long word)
+                               drawSquigglyLineAtIndex(tflIndexFirst, start - 
tflFirst.absoluteStart);
+                               
+                               tflIndex++;
+                               while (tflIndex != tflIndexLast) {
+                                       drawSquigglyLineAtIndex(tflIndex);
+                                       tflIndex++;
+                               }
+                               
+                               drawSquigglyLineAtIndex(tflIndexLast, 0, end - 
tflLast.absoluteStart);
+                       }
+               }
+               
+               // Draw a squiggly line at specific line for specific index 
range
+               private function drawSquigglyLineAtIndex(lineIndex:Number, 
startIndex:Number=0, endIndex:Number=0x7FFFFFFF):void
+               {
+                       var tf:TextFlow = mTextField.textFlow;
+                       var tfl:TextFlowLine = 
tf.flowComposer.getLineAt(lineIndex);
+                       var rectLine:Rectangle = tfl.getBounds();
+                       if (endIndex == 0x7FFFFFFF) {
+                               drawSquigglyLineAtPoint(rectLine.left, 
rectLine.bottom, rectLine.right - rectLine.left);
+                       }
+                       else {
+                               // Force to have a valid TextLine
+                               var tl:TextLine = tfl.getTextLine(true);
+                               
+                               // TODO: atom index and char index is not 
matching for some chars, use try/catch to avoid crash
+                               try {
+                                       var rectFirst:Rectangle = 
tl.getAtomBounds(startIndex);
+                                       var rectLast:Rectangle = 
tl.getAtomBounds(endIndex);
+                                       drawSquigglyLineAtPoint(rectFirst.left 
+ tfl.x, rectLine.bottom, rectLast.right - rectFirst.left);
+                               } catch (err:Error)
+                               {
+                                       //TODO: report error
+                               }
+                       }
+                               
+               }
+               // Draw a squiggly from point x,y with given width, the line is 
drew in mHighlighter 
+               private function drawSquigglyLineAtPoint(x:Number, y:Number, 
width:Number):void
+               {
+                       mHighlighter.graphics.lineStyle(1, 0xfa0707, .65);
+                       mHighlighter.graphics.moveTo(x, y);
+                       var upDirection:Boolean = false;
+                       var offset:uint = 0;
+                       var stepLength:uint = 2;
+                       for ( var i:uint = 1; offset <= width; i++) {
+                               offset = offset + stepLength;
+                               if ( upDirection )
+                                       
mHighlighter.graphics.lineTo(x+offset,y);
+                               else
+                                       
mHighlighter.graphics.lineTo(x+offset,y+stepLength);
+                               upDirection = !upDirection;
+                       }       
+               }
+               
+               private function getValidFirstWordIndex():int{
+                       var index:int = 
SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, 
mTextField, 0 + mTextField.horizontalScrollPosition, 0 + 
mTextField.verticalScrollPosition);
+                       return index;
+
+                       
+               }
+               
+               private function getValidLastWordIndex():int{
+                       var index:int = 
SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, 
mTextField, mTextField.width+mTextField.horizontalScrollPosition, 
mTextField.height+mTextField.verticalScrollPosition);
+                       return index;
+
+               }
+
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkWordProcessor.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkWordProcessor.as
new file mode 100644
index 0000000..c174eee
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SparkWordProcessor.as
@@ -0,0 +1,132 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.ITokenizer;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       import flashx.textLayout.edit.SelectionManager;
+       import flashx.textLayout.tlf_internal;
+       
+       import spark.components.RichEditableText;
+       
+       use namespace tlf_internal;     
+       
+       public class SparkWordProcessor implements IWordProcessor
+       {
+               private var mTextField:RichEditableText;
+
+               public function SparkWordProcessor(textField:RichEditableText)
+               {
+                       if (textField == null ) throw new Error("illegal 
argument."); 
+                       mTextField = textField;
+               }
+                               
+               
+               public function replaceText(token:Token, 
replacement:String):void {
+                       var startIndex:int = token.first;
+                       var endIndex:int = token.last;
+                       
+                       var ta:RichEditableText = mTextField;
+                       var end:int = getValidLastWordIndex();
+                       
+                       if ( replacement == null ) return;
+                       
+                       if (mTextField.text.length<endIndex || startIndex<0) {
+                               return;
+                       }
+                       
+                       var _misspellStart:int = startIndex;
+                       var _misspellEnd:int = endIndex;
+                       
+                       // Workaround for Spark: changes in inactive components 
will trigger strange behavior                   
+                       //var selectedElementRange:ElementRange = 
ElementRange.createElementRange(ta.textFlow, _misspellStart, _misspellEnd);
+                       //var selectedCharacterFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.activePosition == 
ta.textFlow.interactionManager.anchorPosition ? 
ta.textFlow.interactionManager.getCommonCharacterFormat() : 
selectedElementRange.characterFormat;
+                       //var selectedParagraphFormat:ITextLayoutFormat = 
selectedElementRange.paragraphFormat;
+                       //var selectedContainerFormat:ITextLayoutFormat = 
selectedElementRange.containerFormat;
+                       
+                       
+                       
+                       //var selectedCharacterFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonCharacterFormat();
+                       //var selectedContainerFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonContainerFormat();
+                       //var selectedParagraphFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonParagraphFormat();
+                       
+                       /*var tem:EditManager = new EditManager();
+                       ta.textFlow.interactionManager = tem;   */
+                       
+                       
+                       ta.setFocus();
+                       //ta.text = ta.text.substr(0, _misspellStart) + 
replacement + ta.text.substr(_misspellEnd);
+                       
+                       
//tem.applyFormat(selectedCharacterFormat,selectedParagraphFormat,selectedContainerFormat);
+                       //ta.textFlow.flowComposer.updateAllControllers();
+                       
+                       ta.textFlow;
+                       //ta.selectRange(_misspellStart + replacement.length, 
_misspellStart + replacement.length);
+                       ta.selectRange(_misspellStart+1, _misspellEnd);
+                       ta.insertText(replacement);
+                       ta.selectRange(_misspellStart, _misspellStart+1);
+                       ta.insertText("");
+                       
+                       
//ta.textFlow.interactionManager.applyFormat(selectedCharacterFormat,null,null);
+                       
+                       // Workaround for unexpected jump
+                       ta.scrollToRange(end, end);
+               }
+               
+               public function getWordAtPoint(x:uint, y:uint, 
externalTokenizer:ITokenizer=null):Token
+               {
+                       // TODO: use a better alternative than _misspellStart, 
end
+                       var ta:RichEditableText = mTextField;   
+                       var index:int = 
SelectionManager.computeSelectionIndex(ta.textFlow, ta, ta, x, y);
+
+                       if (index >= ta.text.length) return null;
+
+                       var tmpToken:Token = new Token(index,index);
+                       var tokenizer:ITokenizer;
+                       if ( externalTokenizer == null ) {
+                               tokenizer = new TextTokenizer(mTextField.text); 
+                       }else {
+                               tokenizer = externalTokenizer;
+                       }
+                       
+                       var result:Token = new Token(0,0);
+                       var preToken:Token = 
tokenizer.getPreviousToken(tmpToken);
+                       var nextToken:Token = tokenizer.getNextToken(tmpToken);
+                       if ( preToken.last == nextToken.first ) {
+                               result.first = preToken.first;
+                               result.last = nextToken.last;
+                               return result;          
+                       }else {
+                               return null;
+                       }
+                               
+               }
+
+               // TODO: workaround for unexpected jump when word replaced, to 
be refactored for code sharing
+               private function getValidLastWordIndex():int{
+                       var index:int = 
SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, 
mTextField, mTextField.width+mTextField.horizontalScrollPosition, 
mTextField.height+mTextField.verticalScrollPosition);
+                       return index;
+               }
+
+
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SpellingHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SpellingHighlighter.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SpellingHighlighter.as
new file mode 100644
index 0000000..5095331
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/SpellingHighlighter.as
@@ -0,0 +1,179 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import flash.display.Shape;
+       import flash.geom.Point;
+       import flash.geom.Rectangle;
+       import flash.text.TextLineMetrics;
+       
+       import mx.core.IUITextField;
+       import mx.flash.UIMovieClip;
+
+
+       public class SpellingHighlighter extends UIMovieClip
+       {
+               /*
+               * offset point:
+               */
+               private var _offsetPoint:Point;
+               
+               /*
+               * Target TextField.
+               */
+               private var _textField:IUITextField;
+               private static var InvalidIndexValue:int = -2;
+               public function SpellingHighlighter(textField:IUITextField) {
+                       super();
+                       this._textField = textField;
+                       this._offsetPoint = new Point(0,0);
+               }
+               
+               public function drawSquigglyLine(firstCharIndex:int, 
lastCharIndex:int ):void {
+                       var validFirstCharIndex:int = 
getValidFirstCharIndex(firstCharIndex);
+                       var validLastCharIndex:int = 
getValidLastCharIndex(lastCharIndex);
+                       if ( validFirstCharIndex == InvalidIndexValue || 
validLastCharIndex == InvalidIndexValue ){
+                               return;
+                       }
+                       /* draw squiggly line here. */
+                       if ( validFirstCharIndex <= validLastCharIndex ) {
+                               var firstLine:int = 
_textField.getLineIndexOfChar(validFirstCharIndex);
+                               var lastLine:int = 
_textField.getLineIndexOfChar(validLastCharIndex);
+                               //only one line case.
+                               if(lastLine==firstLine)
+                               {
+                                       
drawSingleSquigglyLine(validFirstCharIndex, validLastCharIndex);
+                                       return;
+                               }
+                               //more than one line.
+                               //first line
+                               drawSingleSquigglyLine(validFirstCharIndex, 
_textField.getLineOffset(firstLine)+_textField.getLineLength(firstLine)-1);
+                               //middle....
+                               for(var i:int=firstLine+1;i<lastLine;i++)
+                               {
+                                       
drawSingleSquigglyLine(_textField.getLineOffset(i), 
_textField.getLineOffset(i)+_textField.getLineLength(i)-1);
+                               }
+                               //last lines.
+                               
drawSingleSquigglyLine(_textField.getLineOffset(lastLine), validLastCharIndex);
+                       }
+               }
+               
+               public function drawSingleSquigglyLine(firstCharIndex:int, 
lastCharIndex:int ):void {
+                       var firstLine:int = 
_textField.getLineIndexOfChar(firstCharIndex);
+                       var lastLine:int = 
_textField.getLineIndexOfChar(lastCharIndex);
+                       if ( firstLine != lastLine ) {
+                               return;
+                       }else {
+                               var rect1:Rectangle = 
_textField.getCharBoundaries(firstCharIndex);
+                               var rect2:Rectangle = 
_textField.getCharBoundaries(lastCharIndex);
+                               var x:Number = rect1.x+_offsetPoint.x - 
_textField.scrollH;
+                               var y:Number = rect1.y + rect1.height + 2;
+                               var width:Number = rect2.x+rect2.width-rect1.x;
+                               
+                               // Avoid drawing outside the textField
+                               if (x<0) 
+                               {
+                                       if (x+width > 0) {
+                                               width += x;
+                                               x = 0;
+                                       } 
+                                       else
+                                               return;
+                               }
+                               if (x+width > _textField.width) 
+                               {
+                                       if (x < _textField.width) {
+                                               width = textField.width - x;
+                                       }       
+                                       else
+                                               return;
+                               }
+                               
+                               // The rectangle that bound the string you want
+                               // actual work here.
+                               var myShape:Shape = new Shape();
+                               myShape.graphics.clear();
+                               //myShape.graphics.beginFill(0x0099CC, .35); 
+                               myShape.graphics.lineStyle(1, 0xfa0707, .65);
+                               myShape.graphics.moveTo(x, y);
+                               var upDirection:Boolean = false;
+                               var offset:uint = 0;
+                               var stepLength:uint = 2;
+                               for ( var i:uint = 1; offset <= width; i++) {
+                                       offset = offset + stepLength;
+                                       if ( upDirection )
+                                               
myShape.graphics.lineTo(x+offset,y);
+                                       else
+                                               
myShape.graphics.lineTo(x+offset,y+stepLength);
+                                       upDirection = !upDirection;
+                               }
+                               //myShape.graphics.endFill();
+                               this.addChild(myShape); 
+                       }
+               }
+               
+               private function getValidFirstCharIndex(firstCharIndex:int):int{
+                       if(firstCharIndex<0 || 
firstCharIndex>_textField.text.length-1) 
+                       {
+                               return InvalidIndexValue;
+                       }
+                       var firstLine:Number = 
_textField.getLineIndexOfChar(firstCharIndex);
+                       
+                       if(firstLine<_textField.scrollV-1)
+                       {
+                               firstLine = _textField.scrollV-1;
+                               return _textField.getLineOffset(firstLine);
+                       }
+                       return firstCharIndex;
+               }
+               
+               private function getValidLastCharIndex(lastCharIndex:int):int{
+                       if(lastCharIndex<0 || 
lastCharIndex>_textField.text.length-1) 
+                       {
+                               return InvalidIndexValue;
+                       }
+                       var lastLine:Number = 
_textField.getLineIndexOfChar(lastCharIndex);
+                       if(lastLine>_textField.bottomScrollV-1)
+                       {
+                               lastLine = _textField.bottomScrollV-1;
+                               return 
_textField.getLineOffset(lastLine)+_textField.getLineLength(lastLine)-1;
+                       }
+                       return lastCharIndex;
+               }
+                                       
+               public function set textField(tf:IUITextField):void{
+                       _textField = tf;
+               }
+               
+               public function get textField():IUITextField{
+                       return _textField;
+               }
+               
+               public function set offsetPoint(op:Point):void{
+                       _offsetPoint = op;
+               }
+               
+               public function get offsetPoint():Point{
+                       return _offsetPoint;
+               }
+
+
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFHighlighter.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFHighlighter.as
new file mode 100644
index 0000000..75f6576
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFHighlighter.as
@@ -0,0 +1,248 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.display.Graphics;
+       import flash.display.Shape;
+       import flash.display.Sprite;
+       import flash.geom.Point;
+       import flash.geom.Rectangle;
+       import flash.text.engine.TextLine;
+       import flash.utils.Dictionary;
+       
+       import flashx.textLayout.compose.TextFlowLine;
+       import flashx.textLayout.container.ContainerController;
+       import flashx.textLayout.edit.SelectionManager;
+       import flashx.textLayout.elements.TextFlow;
+       import flashx.textLayout.tlf_internal;
+
+
+       use namespace tlf_internal;     
+
+       /**
+        * <p>This class facilitates drawing of squiggly lines below words for 
TLF TextFlow class.</p>
+        * <p>The TextFlow class is responsible for managing all 
+        * the text content of a story. In TextLayout, text is stored in a 
hierarchical tree of elements. TextFlow is the root object of the element tree. 
+        * All elements on the tree derive from the base class, FlowElement. 
</p> 
+        * TLFHighlighter could be used for drawing squiggly lines in any of 
the custom visual components(probably based on <code>Sprite</code>) which make 
use 
+        * of TextFlow to display text.
+        *      
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       public class TLFHighlighter implements IHighlighter
+       {
+               
+               private var mTextFlow:TextFlow;
+               private var mHighlighter:Dictionary;
+       
+               //private var mHighlighter:Shape;
+               private var ccindex:int;
+               private var cc:ContainerController;
+               /*
+               * offset point:
+               */
+               private var _offsetPoint:Point;
+
+               /**
+                * The constructor for TLFHighlighter.
+                * @param textFlow <code>TextFlow</code> in which to enable 
highlighting.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function TLFHighlighter( textFlow:TextFlow )
+               {
+                       if (textFlow == null ) throw new Error("illegal 
argument."); 
+                       mTextFlow = textFlow;
+                       //mHighlighter = null;
+                       mHighlighter = new Dictionary(true);
+                       this._offsetPoint = new Point(0,0);
+               }
+               /**
+                * Draw squiggly lines below a given token.
+                * @param token <code>Token</code> information of the word to 
be highlighted.            
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function drawSquiggleAt(token:Token):void
+               {
+                       squiggleWord(token);
+               }
+               /**
+                * Clear all squiggly lines in the component.           
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public function clearSquiggles():void
+               {
+                       
+                       for (var idx:int = 0; idx < 
mTextFlow.flowComposer.numControllers; idx++)
+                       {       
+                               var cctmp:ContainerController = 
mTextFlow.flowComposer.getControllerAt(idx);
+                               if (mHighlighter[cctmp.container] != null) {
+                                       
+                                       //ToDO: This assumes single container 
for whole of mTextFlow. Need to implement for multiple container case.
+                                       
cctmp.container.removeChild((mHighlighter[cctmp.container] as Shape));
+                                       
+                                       mHighlighter[cctmp.container] = null;
+                               }       
+                       }
+               }
+       
+               /**
+                * Set offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public function set offsetPoint(op:Point):void{
+                       _offsetPoint = op;
+               }
+               /**
+                * Get offset point information for scrollable controls. This 
is used by the highlighter to move 
+                * the squiggly lines as the text scrolls inside the control.   
+                * @param op offset information as a <code>Point</code> 
instance.                
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */     
+               public function get offsetPoint():Point{
+                       return _offsetPoint;
+               }
+
+               
+
+               // TODO: refactor this code to share with halo components, and 
support words that cross lines
+               private function squiggleWord(token:Token):void {               
                        
+                       var ta:TextFlow = mTextFlow;
+                       
+                       if (!ta) return;                
+                       ccindex = 
ta.flowComposer.findControllerIndexAtPosition(token.first);
+                       
+                       cc = ta.flowComposer.getControllerAt(ccindex);
+                       
+                       if (mHighlighter[cc.container] == null ) {
+                               mHighlighter[cc.container]= new Shape();
+                               (mHighlighter[cc.container] as 
Shape).graphics.clear();
+                               //ccindex = 
ta.flowComposer.findControllerIndexAtPosition(token.first);
+                               
+                               //var cc:ContainerController = 
ta.flowComposer.getControllerAt(ccindex);
+                               //ToDO: This assumes single container for whole 
of mTextFlow. Need to implement for multiple container case.
+                               
cc.container.addChild((mHighlighter[cc.container] as Shape));                   
        
+                       }
+                                       
+                   drawSquigglyLineForRange(token.first, token.last);
+                       
+                       // Just adjust the left padding, top padding is not an 
issue 
+                       //var pleft:uint = mTextFlow.getStyle("paddingLeft");
+                       //mHighlighter.x += pleft;              
+               }
+               
+               // Draw squiggly line
+               private function drawSquigglyLineForRange(start:Number, 
end:Number):void
+               {
+                       // draw squiggly line
+                       var tf:TextFlow = mTextFlow;
+                       var tflFirst:TextFlowLine = 
tf.flowComposer.findLineAtPosition(start);
+                       var tflLast:TextFlowLine = 
tf.flowComposer.findLineAtPosition(end);
+                       var tflIndexFirst:int = 
tf.flowComposer.findLineIndexAtPosition(start);
+                       var tflIndexLast:int = 
tf.flowComposer.findLineIndexAtPosition(end);
+                       
+                       // Pointer
+                       var tflIndex:int = tflIndexFirst;
+                       var tfl:TextFlowLine = tflFirst;
+                       
+                       if (tflIndexFirst == tflIndexLast) {
+                               // Draw one line
+                               drawSquigglyLineAtIndex(tflIndexFirst, start - 
tflFirst.absoluteStart, end - tflFirst.absoluteStart);
+                       } else {
+                               // Multiple lines (very long word)
+                               drawSquigglyLineAtIndex(tflIndexFirst, start - 
tflFirst.absoluteStart);
+                               
+                               tflIndex++;
+                               while (tflIndex != tflIndexLast) {
+                                       drawSquigglyLineAtIndex(tflIndex);
+                                       tflIndex++;
+                               }
+                               
+                               drawSquigglyLineAtIndex(tflIndexLast, 0, end - 
tflLast.absoluteStart);
+                       }
+               }
+               
+               // Draw a squiggly line at specific line for specific index 
range
+               private function drawSquigglyLineAtIndex(lineIndex:Number, 
startIndex:Number=0, endIndex:Number=0x7FFFFFFF):void
+               {
+                       var tf:TextFlow = mTextFlow;
+                       var tfl:TextFlowLine = 
tf.flowComposer.getLineAt(lineIndex);
+                       var rectLine:Rectangle = tfl.getBounds(); 
+                       if (endIndex == 0x7FFFFFFF) {
+                               drawSquigglyLineAtPoint(rectLine.left, 
rectLine.bottom, rectLine.right - rectLine.left, lineIndex);
+                       }
+                       else {
+                               // Force to have a valid TextLine
+                               var tl:TextLine = tfl.getTextLine(true);
+                               
+                               // TODO: atom index and char index is not 
matching for some chars, use try/catch to avoid crash
+                               try {
+                                       var rectFirst:Rectangle = 
tl.getAtomBounds(startIndex);
+                                       var rectLast:Rectangle = 
tl.getAtomBounds(endIndex);
+                                       drawSquigglyLineAtPoint(rectFirst.left 
+ tfl.x, rectLine.bottom, rectLast.right - rectFirst.left, lineIndex);
+                               } catch (err:Error)
+                               {
+                                       //TODO: report error
+                               }
+                       }
+                               
+               }
+               // Draw a squiggly from point x,y with given width, the line is 
drawn in mHighlighter 
+               private function drawSquigglyLineAtPoint(x:Number, y:Number, 
width:Number, lineIndex:Number):void
+               {
+                       var tf:TextFlow = mTextFlow;
+                       var tfl:TextFlowLine = 
tf.flowComposer.getLineAt(lineIndex);
+                       var tl:TextLine = tfl.getTextLine(true);
+                                               
+                       (mHighlighter[cc.container] as 
Shape).graphics.lineStyle(1, 0xfa0707, .65);
+                       (mHighlighter[cc.container] as 
Shape).graphics.moveTo(x, y);
+                       var upDirection:Boolean = false;
+                       var offset:uint = 0;
+                       var stepLength:uint = 2;
+                       for ( var i:uint = 1; offset <= width; i++) {
+                               offset = offset + stepLength;
+                               if ( upDirection )
+                                       (mHighlighter[cc.container] as 
Shape).graphics.lineTo(x+offset,y);
+                               else
+                                       (mHighlighter[cc.container] as 
Shape).graphics.lineTo(x+offset,y+stepLength);
+                               upDirection = !upDirection;
+                       }
+                       
+                       //tl.addChild(mHighlighter);
+                                               
+                       //tf.flowComposer.updateToController(ccindex);
+
+               }
+               
+
+       }
+       
+}
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFWordProcessor.as
 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFWordProcessor.as
new file mode 100644
index 0000000..f506227
--- /dev/null
+++ 
b/Squiggly/main/SpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/TLFWordProcessor.as
@@ -0,0 +1,156 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+       import com.adobe.linguistics.utils.ITokenizer;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       import flashx.textLayout.edit.SelectionManager;
+       import flashx.textLayout.edit.EditManager;
+       import flashx.textLayout.tlf_internal;
+       import flashx.textLayout.elements.TextFlow;
+       
+       import flashx.textLayout.container.ContainerController;
+       import flashx.textLayout.elements.FlowLeafElement;
+       import flashx.textLayout.elements.ParagraphElement;
+       
+       use namespace tlf_internal;     
+       
+       public class TLFWordProcessor implements IWordProcessor
+       {
+               private var mTextFlow:TextFlow;
+               private var _containerController:ContainerController;
+
+               public function TLFWordProcessor(textFlow:TextFlow)
+               {
+                       if (textFlow == null ) throw new Error("illegal 
argument."); 
+                       mTextFlow = textFlow;
+               }
+                               
+               
+               public function replaceText(token:Token, 
replacement:String):void {
+                       var startIndex:int = token.first;
+                       var endIndex:int = token.last;
+                       
+                       var ta:TextFlow = mTextFlow;
+                       //var end:int = getValidLastWordIndex();
+                       
+                       if ( replacement == null ) return;
+                       
+                       /*if (mTextFlow.text.length<endIndex || startIndex<0) {
+                               return;
+                       }*/
+                       
+                       var _misspellStart:int = startIndex;
+                       var _misspellEnd:int = endIndex;
+                       
+                       // Workaround for Spark: changes in inactive components 
will trigger strange behavior                   
+                       //var selectedElementRange:ElementRange = 
ElementRange.createElementRange(ta.textFlow, _misspellStart, _misspellEnd);
+                       //var selectedCharacterFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.activePosition == 
ta.textFlow.interactionManager.anchorPosition ? 
ta.textFlow.interactionManager.getCommonCharacterFormat() : 
selectedElementRange.characterFormat;
+                       //var selectedParagraphFormat:ITextLayoutFormat = 
selectedElementRange.paragraphFormat;
+                       //var selectedContainerFormat:ITextLayoutFormat = 
selectedElementRange.containerFormat;
+                       
+                       
+                       
+                       //var selectedCharacterFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonCharacterFormat();
+                       //var selectedContainerFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonContainerFormat();
+                       //var selectedParagraphFormat:ITextLayoutFormat = 
ta.textFlow.interactionManager.getCommonParagraphFormat();
+                       
+                       var tem:EditManager = ta.interactionManager as 
EditManager;
+                       
+                       
+                       
+                       //ta.setFocus();
+                       //ta.text = ta.text.substr(0, _misspellStart) + 
replacement + ta.text.substr(_misspellEnd);
+                       
+                       
//tem.applyFormat(selectedCharacterFormat,selectedParagraphFormat,selectedContainerFormat);
+                       //ta.textFlow.flowComposer.updateAllControllers();
+                       
+                       //ta.textFlow;
+                       //ta.selectRange(_misspellStart + replacement.length, 
_misspellStart + replacement.length);
+                       
+                       
+                       tem.selectRange(_misspellStart+1, _misspellEnd);
+                       tem.insertText(replacement);
+                       tem.selectRange(_misspellStart, _misspellStart+1);
+                       tem.insertText("");
+                       
+                       
//ta.textFlow.interactionManager.applyFormat(selectedCharacterFormat,null,null);
+                       
+                       // Workaround for unexpected jump
+                       //ta.scrollToRange(end, end);
+               }
+               
+               /**
+                @private
+                (This property is for Squiggly Developer use only.)
+                */
+               public function set 
textFlowContainerController(value:ContainerController):void {
+                       _containerController = value;
+               }
+               
+               public function getWordAtPoint(x:uint, y:uint, 
externalTokenizer:ITokenizer=null):Token
+               {
+                       // TODO: use a better alternative than _misspellStart, 
end
+                       var ta:TextFlow = mTextFlow;    
+                                                                       
+                       var index:int = 
SelectionManager.computeSelectionIndex(ta, _containerController.container, 
_containerController.container, x, y);
+
+                       if (index >= ta.textLength) return null;
+
+                       var currentLeaf:FlowLeafElement = ta.findLeaf(index);
+                       var currentParagraph:ParagraphElement = currentLeaf ? 
currentLeaf.getParagraph() : null;
+                       
+                       var paraStart:uint = 
currentParagraph.getAbsoluteStart();
+                               
+                       //tokenizer = new 
TextTokenizer(currentParagraph.getText().substring());
+                       
+                       var tmpToken:Token = new Token(index - paraStart,index 
- paraStart);
+                       var tokenizer:ITokenizer;
+                       if ( externalTokenizer == null ) {
+                               tokenizer = new 
TextTokenizer(currentParagraph.getText().substring());  
+                       }else {
+                               tokenizer = externalTokenizer;
+                       }
+                       
+                       var result:Token = new Token(0,0);
+                       var preToken:Token = 
tokenizer.getPreviousToken(tmpToken);
+                       var nextToken:Token = tokenizer.getNextToken(tmpToken);
+                       if ( preToken.last == nextToken.first ) {
+                               result.first = preToken.first + paraStart;
+                               result.last = nextToken.last + paraStart;
+                               return result;          
+                       }else {
+                               return null;
+                       }
+                                                       
+               }
+
+               // TODO: workaround for unexpected jump when word replaced, to 
be refactored for code sharing
+               private function getValidLastWordIndex():int{
+                       var index:int = 0;
+                       //var index:int = 
SelectionManager.computeSelectionIndex(mTextFlow.textFlow, mTextFlow, 
mTextFlow, mTextFlow.width+mTextFlow.horizontalScrollPosition, 
mTextFlow.height+mTextFlow.verticalScrollPosition);
+                       return index;
+               }
+
+
+       }
+}
\ No newline at end of file

Reply via email to