http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
new file mode 100644
index 0000000..426ca4c
--- /dev/null
+++ b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
@@ -0,0 +1,562 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+       import com.adobe.linguistics.spelling.UserDictionary;
+       import com.adobe.linguistics.spelling.framework.ResourceTable;
+       import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+       import com.adobe.linguistics.spelling.framework.SpellingService;
+    import com.adobe.linguistics.spelling.ui.HaloHighlighter;
+    import com.adobe.linguistics.spelling.ui.HaloWordProcessor;
+    import com.adobe.linguistics.spelling.ui.IHighlighter;
+    import com.adobe.linguistics.spelling.ui.IWordProcessor;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.events.Event;
+       import flash.events.FocusEvent;
+       import flash.geom.Point;
+       import flash.geom.Rectangle;
+       import flash.net.SharedObject;
+       import flash.net.URLLoader;
+       import flash.net.URLRequest;
+       import flash.text.TextField;
+       import flash.utils.Dictionary;
+       
+       import mx.controls.RichTextEditor;
+       import mx.controls.TextArea;
+       import mx.controls.TextInput;
+       import mx.core.UIComponent;
+       import mx.core.mx_internal;
+       import mx.events.ScrollEvent;
+       
+       use namespace mx_internal;
+       
+       /**
+        * <p>A comprehensive convenience class that bundles a context menu UI, 
+        * the spelling engine, the dictionary loader, and user dictionary 
support 
+        * to enable a single-line integration of spell checking functionality 
into 
+        * any text related Flex UI component.  While this class drastically 
simplifies 
+        * the effort to enable spell checking functionality in a Flex UI 
component, 
+        * it does shield the developer form controlling detailed behaviors of 
the spell 
+        * checker and the user dictionary storage options. </p>
+        *
+        * <p>This class provides a simple UI for some standard Flex UI 
components.
+        *      It is not intended to address a complete user interface.
+        *      Instead, it presents a basic user interface for some commonly 
used Flex UI components.</p>
+        *
+        * <p>For advanced text editing applications, more complex features are 
likely required.
+        *      For those applications, we recommend bypassing this class and 
utilizing the <code>SpellChecker</code> class directly.</p>
+        *
+        * <p><code>SpellUI</code> uses the AdobeSpellingConfig.xml file to 
lookup corresponding resource files for a given locale.
+        * The default location of AdobeSpellingConfig.xml is 
[yourapplicationDirectory]/AdobeSpellingConfig.xml. This could be customized 
using 
+        * <code>spellingConfigUrl</code> property of <code>SpellUI</code>. You 
don't have to change the content of this file. However,
+        * if you want to add a new language, to use an alternative dictionary 
or to customize the location for your dictionaries, you can modify it. 
+        * There's an known issue with IIS web server when loading dictionary 
files with unknown extensions, in which case you can modify the XML to work 
around it.</p><p>
+        * A sample AdobeSpellingConfig.xml will look as follows:
+        * <listing version="3.0">
+        * <pre class="preWrapper">
+        * &lt;?xml version=&quot;1.0&quot; encoding='UTF-8'?&gt;
+        * &lt;SpellingConfig&gt;
+        *      &lt;LanguageResource language=&quot;English&quot;         
languageCode=&quot;en_US&quot; 
ruleFile=&quot;dictionaries/en_US/en_US.aff&quot; 
dictionaryFile=&quot;dictionaries/en_US/en_US.dic&quot;/&gt;
+        *      &lt;LanguageResource language=&quot;Spanish&quot;    
languageCode=&quot;es_ES&quot; 
ruleFile=&quot;dictionaries/es_ES/es_ES.aff&quot; 
dictionaryFile=&quot;dictionaries/es_ES/es_ES.dic&quot;/&gt;
+        *      &lt;LanguageResource language=&quot;Portuguese&quot; 
languageCode=&quot;pt_PT&quot; 
ruleFile=&quot;dictionaries/pt_PT/pt_PT.aff&quot; 
dictionaryFile=&quot;dictionaries/pt_PT/pt_PT.dic&quot;/&gt;
+        *       &lt;LanguageResource language=&quot;Italian&quot;        
languageCode=&quot;it_IT&quot; 
ruleFile=&quot;dictionaries/it_IT/it_IT.aff&quot; 
dictionaryFile=&quot;dictionaries/it_IT/it_IT.dic&quot;/&gt;
+        * &lt;/SpellingConfig&gt;</pre>
+        *
+        * </listing>
+        * Note: The languageCode can be an arbitrary value, as long as you are 
consistent when passing them to the Squiggly classes. 
+        * However, we highly encourage you to follow the two part Unicode 
language identifier format. 
+        * For more information, please consult the latest Unicode Technical 
Standard that can be found at: http://unicode.org/reports/tr35/.</p>
+        * 
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       public class SpellUI
+       {
+               private var hh:IHighlighter;
+               private var hw:IWordProcessor;
+                               
+               
+               private var _checkLastWord:Boolean = true;
+               
+               private var _spellingEnabled:Boolean;
+               
+               private var _actualParent:*;
+               private var isHaloComponent:Boolean;
+
+               //New Added below
+               private var mTextField:TextField;
+                               
+               private var _dictname:String = new String();    
+               
+               private var _userdict:UserDictionary = null;
+               private var _sharedobj:SharedObject = null;
+               private var scm:SpellingContextMenu;    
+               private var _newchecker:SpellChecker = null;
+               private var _resource_locale:Object = null;
+               private var _spellingservice:SpellingService = null;
+               
+               private static var _contextMenuEntries:Object = {enable:"Enable 
Spelling", disable:"Disable Spelling", add:"Add to dictionary"};
+               private static var _spellingConfigUrl:String = 
"AdobeSpellingConfig.xml";
+               
+               private static var _UITable:Dictionary= new Dictionary();
+               private static var _parentTable:Dictionary= new Dictionary();
+               private static var _cacheDictTable:Dictionary= new Dictionary();
+               
+               private static var _configXML:XML = null;
+               private static var _configXMLLoading:Boolean = false;
+               private static var _configXMLLoader:URLLoader = new URLLoader();
+               
+               
+               
+               // Work around for the memory usage problem, ideally a better 
fix is to provide a dicitonary unload function
+               private static var _cache:Object = new Object();
+
+               /**
+                * Enable the spell checking feature in the specified language 
for a UI component. Once a component is spell checking enabled, misspelled 
words will be highlighted with a squiggly line. Users can 
+                * right click on a misspelled word to see the suggestions in 
the context menu.
+                * 
+                *
+                *
+                * @param comp  A text editing Flex UI component. It can be a 
mx <code>TextArea</code>, <code>TextInput</code> or 
<code>RichTextEditor</code>. 
+                * If you are using AdobeSpellingUIEx.swc, it can also be a 
spark <code>TextArea</code> or <code>TextInput</code>.
+                * @param lang  The language code used for spell checking, for 
example <code>en_US</code>. it will lookup the AdobeSpellingConfig.xml file to 
access corresponding resource files.
+                * AdobeSpellingConfig.xml should be located at the same folder 
as your main mxml source file. You don't have to change the content of this 
file. However,
+                * if you want to add a new language, to use an alternative 
dictionary or to customize the location for your dictionaries, you can modify 
it. There's an known issue with
+                * IIS web server when loading dictionary files with unknown 
extensions, in which case you can modify the XML to work around it.
+                * 
+                * 
+                *
+                * @includeExample 
Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public static function enableSpelling(comp:UIComponent, 
lang:String):void
+               {
+                       if ( lang == null ) return;
+                       // TODO: Change dict parameter type to a SpellCheck 
class or a URL string.
+                       var txt:* = getComponentTextModel(comp);
+                       
+                       if ( txt==null || _UITable[comp]!=undefined )
+                               return;
+                       
+                       // TODO: dangerous, is garbage collection going to 
clear this?
+                       _UITable[comp]=new SpellUI(txt, lang);
+                       _parentTable[txt] = comp;
+                       _cacheDictTable[comp]=lang;
+               }
+               
+               /**
+                * Set the spelling context menu entries. This uses the flex 
object as an associative array for extensibility. 
+                * <code>entries</code> should have all the customized 
contextMenu entries including <code>enable (spelling), 
+                * disable (spelling) and add (to dictionary)</code>. To ensure 
a consistent contextMenu within your application, 
+                * the spelling context menu entries you provide here are 
applied to all UI components. We recommend you use this API
+                * with Flex resource for localization. Make sure to also have 
a look at the Flex localization documentation.
+                * 
+                * @see 
http://livedocs.adobe.com/flex/3/html/help.html?content=l10n_1.html 
+                * 
+                * @param entries A flex Ojbect that looks like 
<code>entries:Object = {enable:"Enable Spelling", disable:"Disable Spelling", 
+                * add:"Add to dictionary"}</code>. If you don't customize the 
contextMenu, the default contextMenu in English will be used.
+                * We recommend that you use the Flex localization resource to 
obtain these strings. 
+                * @return <code>True</code> if the spelling menu is 
successfully customized, <code>false</code> if it fails. Possible failure 
+                * reasons include passing the wrong object or missing some 
required entries. If the function fails, the contextMenu is left unchanged.
+                * 
+                * 
+                * @includeExample 
Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
+                * @includeExample 
Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public static function 
setSpellingMenuEntries(entries:Object):Boolean
+               {
+                       if (entries.enable && entries.disable && entries.add && 
(entries.enable != "") && (entries.disable != "") && (entries.add != ""))
+                       {
+                                       _contextMenuEntries = entries;
+                                       return true;
+                       }
+                       else
+                               return false;
+               }
+
+               /**
+                * Get the spelling context menu entries. 
+                * 
+                * @return A flex <code>Object</code> containing the spelling 
context menu entries. If you haven't customized the entries, you get the 
default associative array <code>{enable:"Enable Spelling", disable:"Disable 
Spelling", add:"Add to dictionary"}</code>
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */             
+               public static function getSpellingMenuEntries():Object
+               {
+                       return _contextMenuEntries;
+               }
+                       
+               /**
+                * The URL for the spelling config xml file. If you haven't 
specified it, the default URL is 
[applicationDirectory]/AdobeSpellingConfig.xml. Note that we don't validate the 
URL, if the file doesn't exist, you will get an error when calling 
enableSpelling() function.
+                *
+                * @example The following code customize the spellingConfigUrl 
before enabling spell checking.
+                * <listing version="3.0">
+                * SpellUI.spellingConfigUrl = "./config/MySpellingConfig.xml";
+                * SpellUI.enableSpelling(textArea, "es_ES");
+                * </listing>
+                */
+               public static function get spellingConfigURL():String
+               {
+                       return _spellingConfigUrl;
+               }
+               
+               public static function set spellingConfigURL(url:String):void
+               {
+                       if (url == null) throw new Error("URL can't be null");
+                       _spellingConfigUrl = url;
+               }
+               
+
+                       
+               /**
+                * Disable the spell checking feature for a UI component.
+                * 
+                * @param comp  A text editing Flex UI component.
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               public static function disableSpelling(comp:UIComponent):void{
+                       if ( _UITable[comp] == undefined )
+                               return;
+                       var _ui:SpellUI = _UITable[comp];
+                       if ( _ui != null) _ui.cleanUp();
+                       var dictName:String = _cacheDictTable[comp];
+                       var cleanUPDictionaryCount:int = 0;
+                       for each ( var _dictName:String in _cacheDictTable ) {
+                               if ( _dictName == dictName  )
+                                       cleanUPDictionaryCount++;
+                       }
+                       if ( cleanUPDictionaryCount == 1 ) {
+                               _cache[dictName] = undefined;
+                       }
+                       delete _UITable[comp];
+                       delete _cacheDictTable[comp];
+                       
+               }
+               
+               /**
+                @private
+                (This property is for Squiggly Developer use only.)
+                */
+               public static function get UITable():Dictionary {
+                       return _UITable;
+               }
+               
+               /**
+                @private
+                (This property is for Squiggly Developer use only.)
+                */
+               public function set spellingEnabled(value:Boolean):void {
+                       _spellingEnabled = value;
+               }
+               
+               /**
+                @private
+                (This property is for Squiggly Developer use only.)
+                */
+               public static function get parentComp():Dictionary {
+                       return _parentTable;
+               }
+               
+               private static function 
getComponentTextModel(comp:UIComponent):* {
+                       var txt:TextField = null;
+                       if ( (comp == null) || !( (comp is TextArea) || (comp 
is TextInput) || (comp is RichTextEditor) ) )
+                               return null;
+                       if ((comp as RichTextEditor) != null) {
+                               txt = (comp as 
RichTextEditor).textArea.getTextField() as TextField;
+                       }
+                       else if ((comp as TextArea) != null){
+                               txt = (comp as TextArea).getTextField() as 
TextField;
+                       }
+                       else if ((comp as TextInput) != null) {
+                               txt = (comp as TextInput).getTextField() as 
TextField;
+                       }
+                       else {
+                               // do nothing if it's not a valid text component
+                               return null;
+                       }
+                       return txt;
+               }
+               
+               /**
+                * Constructs a SpellUI object.
+                *      @private
+                *
+                *      @param  textFiled       A Flex UI component to include 
spell-check capability
+                *      @param lang     The language code used for spell 
checking
+                *
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */                     
+               public function SpellUI(textModel:*, lang:String)
+               {               
+                       // TODO: Consider making this method invisible to user, 
only expose the static function.
+                       if ( textModel is TextField ) {
+                               isHaloComponent=true;
+                       }else {
+                               // do nothing, we only accept textField and 
TextFlow here....
+                               return;
+                       }
+                       _actualParent = textModel;
+                       
+                       //New Added below -- check if text field needs to be 
extracted from textModel
+                       mTextField = textModel;
+                                               
+                       mTextField.addEventListener(FocusEvent.FOCUS_OUT, 
handleFocusOut);
+                       mTextField.addEventListener(ScrollEvent.SCROLL, 
spellCheckScreen);
+                       mTextField.parent.addEventListener(Event.RENDER, 
spellCheckScreen);
+                       mTextField.parent.addEventListener(Event.CHANGE, 
handleChangeEvent);
+                       _dictname = lang;                       
+                       loadConfig();
+                       
+               }
+               
+               private function spellCheckScreen(event:Event):void
+               {
+                       doSpellingJob();
+               }
+               
+               private function handleFocusOut(event:FocusEvent):void
+               {
+                       _checkLastWord = true;
+                       doSpellingJob();
+               }
+               
+               private function handleChangeEvent( event:Event ) :void {
+                       _checkLastWord = false;
+                       doSpellingJob();
+               }
+                               
+               /*private function doSpelling():void
+               {
+                       _checkLastWord = true;
+                       doSpellingJob();
+               }*/
+               
+               /**
+                @private
+                (This property is for Squiggly Developer use only.)
+                */             
+               public function doSpellingJob():void
+               {
+                       if (_spellingEnabled == false) return;
+                       spellCheckRange(getValidFirstWordIndex(), 
getValidLastWordIndex());
+               }
+               
+               private function spellCheckRange(start:uint, end:uint):void {
+                       //hh.preSpellCheckRange(start, end);
+                       hh.clearSquiggles();
+                       
+                       //if (end <= start) return;
+                       var firstLine:int = 
mTextField.getLineIndexOfChar(start);
+                       var rect:Rectangle = 
mTextField.getCharBoundaries(start);
+                       var counter:uint = start;
+                       var numLines:Number = 0;
+                       
+                       /* mTextField.getCharBoundaries returns null for blank 
lines and for end of line characters. Placing this workaround
+                       to count line heights until a non-null bounding 
rectangle is found */
+                       
+                       while (rect == null) {
+                               if (counter+1 > end) {
+                                               rect = new Rectangle(0,0,0,0);
+                                               break;
+                                       }                               
+                               if(mTextField.text.charCodeAt(counter)<0x0300 
|| mTextField.text.charCodeAt(counter)>0x036F)//not in diacritic combining range
+                               {
+                                       numLines += 
mTextField.getLineMetrics(firstLine).height;
+                                       firstLine++;
+                               }
+                               counter++;
+                               rect = mTextField.getCharBoundaries(counter);
+                       }
+                       
+                       var yoffset:Number = rect.y - numLines; 
+                       var pleft:uint = (mTextField.parent as 
UIComponent).getStyle("paddingLeft");
+                       var ptop:uint = (mTextField.parent as 
UIComponent).getStyle("paddingTop");
+                       
+                       var offsetPoint:Point = new Point(pleft, ptop-yoffset); 
+                                               
+                       var tokenizer:TextTokenizer = new 
TextTokenizer(mTextField.text.substring(start,end));
+                       //var seps:Vector.<int> = new Vector.<int>();
+                       //seps.push(new int(34));
+                       //tokenizer.ignoredSeperators = seps;
+                       var tokens:Vector.<Token> = new Vector.<Token>();
+                       
+                       hh.offsetPoint = offsetPoint;
+                       
+                       for ( var token:Token = tokenizer.getFirstToken(); 
token != tokenizer.getLastToken(); token= tokenizer.getNextToken(token) ) {
+                               var 
result:Boolean=_spellingservice.checkWord(mTextField.text.substring(token.first+start,
 token.last+start));                                  
+                               if (!result){
+                                       if (_checkLastWord || (token.last+start 
!= mTextField.text.length)) 
+                                               
//hh.highlightWord(token.first+start, token.last+start-1);
+                                               //tokens.push(new 
Token(token.first+start, token.last+start-1));
+                                               hh.drawSquiggleAt(new 
Token(token.first+start, token.last+start-1));
+                               }
+                               
+                       }
+                       //hh.postSpellCheckRange(start, end);
+                       //hh.offsetPoint = offsetPoint;
+                       //hh.drawSquiggles(tokens);
+               }
+               
+               
+               private function getValidFirstWordIndex():int{
+                       return mTextField.getLineOffset(mTextField.scrollV-1);
+               }
+               
+               private function getValidLastWordIndex():int{
+                       return 
mTextField.getLineOffset(mTextField.bottomScrollV-1)+mTextField.getLineLength(mTextField.bottomScrollV-1);
+               }
+
+               private function loadConfig():void{
+                       _resource_locale = 
SpellingConfiguration.resourceTable.getResource(_dictname);
+                       
+                       if ((_resource_locale != null) || (SpellUI._configXML 
!= null)) 
+                               loadConfigComplete(null);
+                       else {  
+                               
SpellUI._configXMLLoader.addEventListener(Event.COMPLETE, loadConfigComplete);
+                       
+                               if (SpellUI._configXMLLoading == false)
+                               {
+                                       SpellUI._configXMLLoader.load(new 
URLRequest(_spellingConfigUrl));
+                                       SpellUI._configXMLLoading = true;
+                               }
+                       }
+               }
+               
+               private function loadConfigComplete(evt:Event):void{
+                       if (_resource_locale == null) {
+                               if (SpellUI._configXML == null)
+                                       SpellUI._configXML= new 
XML(evt.target.data);
+                       
+                               
SpellingConfiguration.resourceTable.setResource(_dictname,{rule:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@ruleFile,
 
+                                                                               
                                                                
dict:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@dictionaryFile});
+                       }
+                       //New Added
+                       _spellingservice = new SpellingService(_dictname);
+                       _spellingservice.addEventListener(Event.COMPLETE, 
loadDictComplete);
+                       _spellingservice.init();
+               }
+               
+
+               
+               
+               private function loadDictComplete(evt:Event):void
+               {                                       
+                       
+                       
+                       // Lazy loading the UD only when the main dict is 
loaded successfully
+                       if ((SpellUI._cache["Squiggly_UD"] as UserDictionary) 
== null)
+                       {
+                               _sharedobj = 
SharedObject.getLocal("Squiggly_v03");
+                               var vec:Vector.<String> = new Vector.<String>();
+                               if (_sharedobj.data.ud) {
+                                       for each (var w:String in 
_sharedobj.data.ud)
+                                               vec.push(w);
+                               }
+                               _userdict = new UserDictionary(vec);
+                               
+                               SpellUI._cache["Squiggly_SO"] = _sharedobj;
+                               SpellUI._cache["Squiggly_UD"] = _userdict;
+                       }
+                       else 
+                       {
+                               _sharedobj = SpellUI._cache["Squiggly_SO"];
+                               _userdict = SpellUI._cache["Squiggly_UD"];
+                       }
+                       _spellingservice.addUserDictionary(_userdict);
+                       //Adding default behaviour to accomodate ignoring of 
abbreviations bug#2756840
+                       _spellingservice.ignoreWordWithAllUpperCase=true;
+                       
+                       
+                       // Add the context menu, this might be not successful
+                       scm = null;
+                       try {
+                               addContextMenu(null);
+                       }
+                       catch (err:Error)
+                       {
+                               // TODO: error handling here
+                       }
+                       _actualParent.addEventListener(Event.ADDED_TO_STAGE, 
addContextMenu);
+               }
+               
+
+               private function addContextMenu(event:Event):void
+               {
+                       if ( scm != null ) return;
+                       if ( isHaloComponent ) {
+                               hh= new HaloHighlighter( _actualParent);
+                               hw= new HaloWordProcessor( _actualParent);
+                       }else {
+                               trace("error now, later will be true");
+                       }
+               
+                       scm =  new SpellingContextMenu(hh, hw, 
_spellingservice, _actualParent, _actualParent.contextMenu); 
+                       scm.setIgnoreWordCallback( addWordToUserDictionary );
+                       
+                       // Halo need this
+                       if (_actualParent.contextMenu == null)
+                       {
+                               _actualParent.contextMenu = scm.contextMenu;
+                       }
+                       
+                       //hh.spellingEnabled=true;
+                       _spellingEnabled = true;
+                       try {
+                               doSpellingJob();
+                       }
+                       catch (err:Error)
+                       {
+                               // If it fails here, it should later triggered 
by the render event, so no need to do anything
+                       }
+                       
+                       
+               }
+               
+               private function addWordToUserDictionary(word:String):void
+               {
+                       _userdict.addWord(word);
+                       
+                       // TODO: serialization here might affect ther 
performance
+                       _sharedobj.data.ud = _userdict.wordList;
+                       
+               }
+               /**
+                *      @private
+                */
+               private function cleanUp():void {
+                       hh.clearSquiggles();
+                       scm.cleanUp();
+                       _actualParent.removeEventListener(Event.ADDED_TO_STAGE, 
addContextMenu);
+                       
+                       mTextField.removeEventListener(ScrollEvent.SCROLL, 
spellCheckScreen);
+                       mTextField.parent.removeEventListener(Event.RENDER, 
spellCheckScreen);
+                       mTextField.parent.removeEventListener(Event.CHANGE, 
handleChangeEvent);
+                       mTextField.removeEventListener(FocusEvent.FOCUS_OUT, 
handleFocusOut);   
+               }
+               
+       }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
new file mode 100644
index 0000000..d84f325
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
@@ -0,0 +1,243 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+       import com.adobe.linguistics.spelling.framework.SpellingService;
+       import com.adobe.linguistics.utils.Token;
+       import com.adobe.linguistics.utils.TextTokenizer;
+       
+       import flash.events.ContextMenuEvent;
+       import flash.events.Event;
+       import flash.events.EventDispatcher;
+       
+       import flash.ui.ContextMenu;
+       import flash.ui.ContextMenuItem;
+       
+       import flash.text.TextField;
+       import mx.core.UIComponent;
+       
+       import flash.geom.Point;
+       import flash.geom.Rectangle;
+       import com.adobe.linguistics.spelling.ui.IHighlighter;
+       import com.adobe.linguistics.spelling.ui.IWordProcessor;
+       
+       public class SpellingContextMenu
+       {
+               private var disableMenuItem:ContextMenuItem = new 
ContextMenuItem("Disable spell checking",true);
+               private var enableMenuItem:ContextMenuItem = new 
ContextMenuItem("Enable spell checking");
+               private var controlMenuItemList:Array = new Array();
+               private var suggestionMenuItemList:Array = new Array();
+               private var _spellingEnabled:Boolean;
+               private var _contextMenu:ContextMenu;
+               private var mTextHighlighter:IHighlighter;
+               private var mWordProcessor:IWordProcessor;
+               private var mSpellEngine:SpellingService;
+               private var mParentTextField:TextField;
+               private var _ignoreWordFunctionProcessor:Function;
+               private var _misspelledToken:Token;
+               private var _misspelled:String;
+               public function 
SpellingContextMenu(textHighlighter:IHighlighter, wordProcessor:IWordProcessor, 
engine:SpellingService, actualParent:*, contextMenu:ContextMenu=null)
+               {
+                       
+                       if ( textHighlighter == null || wordProcessor == null 
||  engine == null) throw new Error("illegal argument."); 
+                       mTextHighlighter = textHighlighter;
+                       mWordProcessor = wordProcessor;
+                       mSpellEngine = engine;
+                       mParentTextField = actualParent;
+                       if (contextMenu != null) {
+                               _contextMenu =contextMenu;
+                       }else {
+                               _contextMenu = new ContextMenu();
+                       }
+                       
enableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, 
handleEnableSpellCheck);
+                       
disableMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, 
handleDisableSpellCheck);
+                       controlMenuItemList.push(enableMenuItem);
+                       controlMenuItemList.push(disableMenuItem);
+                       
+                       _contextMenu.customItems.push(disableMenuItem);
+                       _contextMenu.customItems.push(enableMenuItem);
+                       spellingEnabled = true; //default value
+                       //spellingEnabled= mTextHighlighter.spellingEnabled;
+                       
_contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, 
handleContextMenuSelect);
+                       _ignoreWordFunctionProcessor=null;
+               }
+               
+               public function cleanUp():void
+               {
+                       mTextHighlighter=null;
+                       mWordProcessor=null;
+                       spellingEnabled = false;
+                       _ignoreWordFunctionProcessor=null;
+                       
+                       
_contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, 
handleContextMenuSelect);
+                       
+                       var removedNum:int = 0;
+                       var count:uint = _contextMenu.customItems.length;
+                       for (var j:uint=count; j>0; j--) {
+                               if ( isWordItem(_contextMenu.customItems[j-1]) 
|| isControlItem(_contextMenu.customItems[j-1]) ) {
+                                       _contextMenu.customItems.splice(j-1,1);
+                                       removedNum++
+                               }
+                       }
+                       if ( removedNum != suggestionMenuItemList.length + 
controlMenuItemList.length ) {
+                               trace("internal error");
+                       }
+                       
+                       suggestionMenuItemList = null;
+                       controlMenuItemList = null;
+               }
+               
+               public function get contextMenu():ContextMenu {
+                       return this._contextMenu;
+               }
+
+               private function 
handleContextMenuSelect(event:ContextMenuEvent):void
+               {
+                       /* Clear the context menu */
+                       //spellingEnabled= mTextHighlighter.spellingEnabled;
+                       //SpellUI.doSpelling1();
+                       var removedNum:int = 0;
+                       var count:uint = _contextMenu.customItems.length;
+                       for (var j:uint=count; j>0; j--) {
+                               if ( isWordItem(_contextMenu.customItems[j-1]) 
) {
+                                       _contextMenu.customItems.splice(j-1,1);
+                                       removedNum++
+                               }
+                       }
+                       if ( removedNum != suggestionMenuItemList.length ) {
+                               trace("internal error");
+                       }
+                       
+                       
+                       suggestionMenuItemList = new Array();
+       
+                       // localized entries
+                       var entries:Object = SpellUI.getSpellingMenuEntries();
+                       disableMenuItem.caption = entries.disable;
+                       enableMenuItem.caption = entries.enable;                
                
+
+                       if (spellingEnabled == true) {
+                               _misspelledToken = 
mWordProcessor.getWordAtPoint(mParentTextField.mouseX, mParentTextField.mouseY);
+                               if (_misspelledToken==null) return;
+                               _misspelled =   
mParentTextField.text.substring(_misspelledToken.first, _misspelledToken.last);
+                               if ((_misspelled==null) || (_misspelled == "")) 
return;
+                               
+                               if (mSpellEngine.checkWord(_misspelled)==true) 
return;                          
+                               
+                               var suseAddToItem:ContextMenuItem = new 
ContextMenuItem(entries.add);
+                               
suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, 
handleAddToItemSelect);
+                               suggestionMenuItemList.push(suseAddToItem);
+                               
_contextMenu.customItems.splice(0,0,suseAddToItem);     
+                               //var result:Array = 
mWordProcessor.getSuggestionsAtPoint();
+                               var resultVector:Vector.<String> = 
mSpellEngine.getSuggestions(_misspelled);
+                               var result:Array = new Array();
+                               if (resultVector) {
+                                       for each (var w:String in resultVector)
+                                       result.push(w);
+                               }
+                               if (result!=null) {
+                                       for (var i:int=result.length-1;i>=0;i-- 
) {
+                                               var 
suseMenuItem:ContextMenuItem = new ContextMenuItem(result[i]);
+                                               
suseMenuItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, 
handleSuseItemSelect);
+                                               
suggestionMenuItemList.push(suseMenuItem);
+                                               
//_contextMenu.customItems.push(suseMenuItem);
+                                               
_contextMenu.customItems.splice(0,0,suseMenuItem);
+                                       }
+                               }
+                       }
+                       
+
+                       
+               }
+               
+               public function setIgnoreWordCallback(func:Function ) :void {
+                       if ( func != null )
+                       _ignoreWordFunctionProcessor = func;
+               }
+               
+               private function 
handleAddToItemSelect(event:ContextMenuEvent):void
+               {
+                       if ( _ignoreWordFunctionProcessor == null ) return;
+                       
+                       /*
+                       var menuEntry:String = (event.currentTarget as 
ContextMenuItem).caption;
+                       var start:uint = 5;
+                       var end:uint = menuEntry.length - 15;
+                       var word:String = menuEntry.substring(start, end);
+                       */
+                       _ignoreWordFunctionProcessor(_misspelled);
+                       
//SpellUI.UITable[SpellUI.parentComp[mParentTextField]].doSpellingJob();//Reason
 bug#2713972 Fix Added Under
+                       //now implicitly calling dospelling on all text areas
+                       for each (var tempUIComponent:SpellUI in 
SpellUI.UITable)
+                       {
+                               tempUIComponent.doSpellingJob();
+                       }
+               }
+
+               private function isWordItem(item:ContextMenuItem):Boolean {
+                       
+                       for ( var i:int=0; i<suggestionMenuItemList.length; ++i 
) {
+                               if ( suggestionMenuItemList[i] == item ) return 
true;
+                       }
+                       return false;
+               }
+               
+               private function isControlItem(item:ContextMenuItem):Boolean {
+                       for (var i:int=0; i<controlMenuItemList.length; ++i) {
+                               if ( controlMenuItemList[i] == item) return 
true;
+                       }
+                       return false;
+               }
+
+               private function 
handleSuseItemSelect(event:ContextMenuEvent):void
+               {
+                       mWordProcessor.replaceText(_misspelledToken, 
(event.currentTarget as ContextMenuItem).caption );
+                       
SpellUI.UITable[SpellUI.parentComp[mParentTextField]].doSpellingJob();
+               }
+
+               
+               private function set spellingEnabled(value:Boolean) :void {
+                       _spellingEnabled = value;
+                       disableMenuItem.visible=spellingEnabled;
+                       enableMenuItem.visible=!spellingEnabled;
+               }
+               private function get spellingEnabled():Boolean {
+                       return this._spellingEnabled;
+               }
+               private function 
handleEnableSpellCheck(event:ContextMenuEvent):void
+               {
+                       spellingEnabled= true;
+                       //mTextHighlighter.spellingEnabled= spellingEnabled;
+                       //SpellUI.doSpellingJob();
+                       //dispatchEvent(new Event(Event.RENDER));
+                       
+                       
SpellUI.UITable[SpellUI.parentComp[mParentTextField]].spellingEnabled = 
spellingEnabled;
+                       
SpellUI.UITable[SpellUI.parentComp[mParentTextField]].doSpellingJob();
+                       //spellCheckRange(getValidFirstWordIndex(), 
getValidLastWordIndex());
+               }
+               private function 
handleDisableSpellCheck(event:ContextMenuEvent):void
+               {
+                       spellingEnabled= false;
+                       
SpellUI.UITable[SpellUI.parentComp[mParentTextField]].spellingEnabled = 
spellingEnabled;
+                       mTextHighlighter.clearSquiggles();
+               }
+                               
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
new file mode 100644
index 0000000..91b0d5f
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.ui
+{
+       import __AS3__.vec.Vector;
+       
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.geom.Point;
+       import flash.text.TextField;
+       
+       import mx.core.IUITextField;
+       import com.adobe.linguistics.spelling.ui.IHighlighter;
+       import com.adobe.linguistics.spelling.ui.SpellingHighlighter;
+
+       /**
+        * <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 10
+        * @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/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
new file mode 100644
index 0000000..9c05b3b
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
@@ -0,0 +1,112 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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;
+       import com.adobe.linguistics.spelling.ui.IWordProcessor;
+
+
+       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/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
new file mode 100644
index 0000000..3b5a309
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
@@ -0,0 +1,67 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.ui
+{
+       import com.adobe.linguistics.utils.Token;
+       import __AS3__.vec.Vector;
+       import flash.geom.Point;
+       
+       /**
+        * The <code>IHighlighter</code> Interface.
+        * This interface defines default methods which will be used for 
highlighting text in UI components.
+        *
+        * @playerversion Flash 10
+        * @langversion 3.0
+        */
+       
+       public interface IHighlighter
+       {
+               /**
+                * 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
+                */
+               function drawSquiggleAt(token:Token):void;
+               /**
+                * Clear all squiggly lines in the UI.          
+                * @playerversion Flash 10
+                * @langversion 3.0
+                */
+               function clearSquiggles():void;
+               /**
+                * 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
+                */             
+               function set offsetPoint(op:Point):void;
+               /**
+                * 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
+                */             
+               function get offsetPoint():Point;
+               
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
new file mode 100644
index 0000000..8196691
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/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.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/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
new file mode 100644
index 0000000..ffe9653
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
@@ -0,0 +1,229 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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;
+       import com.adobe.linguistics.spelling.ui.IHighlighter;
+
+       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);
+                               if(tl==null) return;
+                               var atomStartIndex:int= 
tl.getAtomIndexAtCharIndex(startIndex+ tl.textBlockBeginIndex);//fix for 
diacritic characters bug#2854971(adding textBlockBeginIndex since 
getAtomIndexAtCharIndex is relative to beginning of block)
+                               var atomEndIndex:int= 
tl.getAtomIndexAtCharIndex(endIndex+tl.textBlockBeginIndex);//fix for diacritic 
characters bug#2854971
+                               // TODO: atom index and char index is not 
matching for some chars, use try/catch to avoid crash
+                               try {
+                                       var rectFirst:Rectangle = 
tl.getAtomBounds(atomStartIndex);
+                                       var rectLast:Rectangle = 
tl.getAtomBounds(atomEndIndex);
+                                       drawSquigglyLineAtPoint(rectFirst.left 
+ tfl.x, rectLine.bottom, rectLast.right - rectFirst.left);
+                               } catch (err:Error)
+                               {
+                                       trace(err);
+                               }
+                       }
+                               
+               }
+               // 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/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
new file mode 100644
index 0000000..3ae7a88
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
@@ -0,0 +1,133 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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;
+       import com.adobe.linguistics.spelling.ui.IWordProcessor;
+       
+       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/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
new file mode 100644
index 0000000..27cd2fb
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
@@ -0,0 +1,196 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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 line:int;
+                               while(rect1==null){ 
+                                       
line=_textField.getLineIndexOfChar(firstCharIndex);
+                                       if( 
(firstCharIndex+1)>(_textField.getLineOffset(line)+_textField.getLineLength(line)-1)||(firstCharIndex+1)>lastCharIndex)
 return;// go till the last character
+                                       firstCharIndex++;
+                                       rect1= 
_textField.getCharBoundaries(firstCharIndex);                                   
                                         
+                               }
+                               
+                               while(rect2==null){//this case appears for 
diacritic characters made using Decomposed chars
+                                       
line=_textField.getLineIndexOfChar(lastCharIndex);
+                                       if( lastCharIndex-1 < 
(_textField.getLineOffset(line))||firstCharIndex>(lastCharIndex-1) ) return; 
//go till the first character
+                                       lastCharIndex--;// check for the 
previos character
+                                       rect2= 
_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(0,0);
+                               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/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
new file mode 100644
index 0000000..92b7c71
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
@@ -0,0 +1,252 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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;
+       import com.adobe.linguistics.spelling.ui.IHighlighter;
+
+
+       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 (!cctmp) return;     
+                               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 (!cc) return;        
+                       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);
+                               if(tl==null)return;
+                               var atomStartIndex:int= 
tl.getAtomIndexAtCharIndex(startIndex+ tl.textBlockBeginIndex);//fix for 
diacritic characters bug#2854971
+                               var atomEndIndex:int= 
tl.getAtomIndexAtCharIndex(endIndex+ tl.textBlockBeginIndex);//fix for 
diacritic characters bug#2854971
+                               // TODO: atom index and char index is not 
matching for some chars, use try/catch to avoid crash
+                               try {
+                                       var rectFirst:Rectangle = 
tl.getAtomBounds(atomStartIndex);
+                                       var rectLast:Rectangle = 
tl.getAtomBounds(atomEndIndex);
+                                       drawSquigglyLineAtPoint(rectFirst.left 
+ tfl.x, rectLine.bottom, rectLast.right - rectFirst.left, lineIndex);
+                               } catch (err:Error)
+                               {
+                                       trace(err);
+                               }
+                       }
+                               
+               }
+               // 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/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
new file mode 100644
index 0000000..749e218
--- /dev/null
+++ 
b/Squiggly/main/SpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
@@ -0,0 +1,159 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.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;
+       import com.adobe.linguistics.spelling.ui.IWordProcessor;
+       
+       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, _misspellEnd-1);
+                       //tem.insertText(replacement);
+                       //tem.selectRange(_misspellStart, _misspellStart+1);
+                       //tem.insertText("");
+                       tem.overwriteText(replacement);
+                       
+                       
//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;
+                       
+                       if (currentParagraph == null) return 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

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
 
b/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
new file mode 100644
index 0000000..28f16e6
--- /dev/null
+++ 
b/Squiggly/main/SpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
@@ -0,0 +1,87 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.ui
+{
+       import __AS3__.vec.Vector;
+       
+       import com.adobe.linguistics.utils.Token;
+       
+       import flash.geom.Point;
+       import flash.text.TextField;
+       
+       import mx.core.IUITextField;
+
+
+       public class HaloHighlighter implements IHighlighter
+       {
+               private var mTextField:TextField;
+               private var mHighlighter:SpellingHighlighter;
+               /*
+               * offset point:
+               */
+               private var _offsetPoint:Point;
+
+               public function HaloHighlighter( textField:TextField )
+               {
+                       if (textField == null ) throw new Error("illegal 
argument."); 
+                       mTextField = textField;
+                       mHighlighter = null;
+                       this._offsetPoint = new Point(0,0);
+               }
+               /*************************Public 
function************************************/
+               public function drawSquiggles(tokens:Vector.<Token>):void
+               {
+                       spellCheckRange(tokens);
+               }
+               
+               public function clearSquiggles():void
+               {
+                       if (mHighlighter) {
+                               mTextField.parent.removeChild(mHighlighter);
+                               mHighlighter=null;
+                       }
+                       
+               }
+
+               public function set offsetPoint(op:Point):void{
+                       _offsetPoint = op;
+               }
+               
+               public function get offsetPoint():Point{
+                       return _offsetPoint;
+               }
+
+
+               private function spellCheckRange(tokens:Vector.<Token>):void {
+                       
+                       mHighlighter= new SpellingHighlighter( mTextField as 
IUITextField);
+                       
+                       
+                       for ( var i:int = 0; i< tokens.length; ++i ) {
+                               var _token:Token = tokens[i];
+                               mHighlighter.drawSquigglyLine(_token.first, 
_token.last);
+                       }
+                       
+                       mTextField.parent.addChild(mHighlighter);       
+                       mHighlighter.move(_offsetPoint.x, _offsetPoint.y);
+               }
+
+       }
+}
\ No newline at end of file

Reply via email to