You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/04/25 07:27:06 UTC

[01/18] Squiggly spell checker donation from Adobe Systems Inc.

Repository: flex-utilities
Updated Branches:
  refs/heads/develop e3d273765 -> a52655acc


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo-app.xml b/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo-app.xml
new file mode 100644
index 0000000..36fb899
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo-app.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 
+ 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.
+ 
+ -->
+<application xmlns="http://ns.adobe.com/air/application/1.5">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- The application identifier string, unique to this application. Required. -->
+	<id>AdobeSpellingAirDemo</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>AdobeSpellingAirDemo</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>AdobeSpellingAirDemo</name>
+
+	<!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
+	<version>v1</version>
+
+	<!-- Description, displayed in the AIR application installer.
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flex Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flex Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+	</initialWindow>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+		 specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image48x48></image48x48>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo.mxml b/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo.mxml
new file mode 100644
index 0000000..4c68739
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingAirDemo/src/AdobeSpellingAirDemo.mxml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="1024" height="768" initialize="init()">		
+			<mx:Script>
+			<![CDATA[
+
+				import com.adobe.linguistics.spelling.SpellUI;
+				
+				public function init():void
+				{
+					SpellUI.enableSpelling(ti, "usa.zwl");
+					SpellUI.enableSpelling(ta, "usa.zwl");
+					SpellUI.enableSpelling(rte, "usa.zwl");
+				}	
+			]]>
+    		</mx:Script>
+    		
+			<mx:Label text="Squiggly Spell Checker Air Demo v0.1" fontSize="30"/>
+    		<mx:TextInput id="ti" width="50%" fontSize="30"/>
+			<mx:TextArea id="ta" width="50%" height="50%" fontSize="30"/>
+			<mx:RichTextEditor id="rte" width="50%" height="50%" fontSize="30"/>	
+</mx:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx-app.xml b/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx-app.xml
new file mode 100644
index 0000000..95c29b4
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx-app.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!--
+ 
+ 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.
+ 
+ -->
+<application xmlns="http://ns.adobe.com/air/application/1.5.2">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5.2
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- The application identifier string, unique to this application. Required. -->
+	<id>AdobeSpellingAirDemoEx</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>AdobeSpellingAirDemoEx</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>AdobeSpellingAirDemoEx</name>
+
+	<!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
+	<version>v1</version>
+
+	<!-- Description, displayed in the AIR application installer.
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flash Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flash Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+	</initialWindow>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+		 specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image48x48></image48x48>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx.mxml b/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx.mxml
new file mode 100644
index 0000000..e8912c9
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingAirDemoEx/src/AdobeSpellingAirDemoEx.mxml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
+					   xmlns:s="library://ns.adobe.com/flex/spark" 
+					   xmlns:mx="library://ns.adobe.com/flex/mx">
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	
+	<fx:Script>
+		<![CDATA[
+			
+			import com.adobe.linguistics.spelling.SpellUI;   		           
+			
+			private function EnableAll(evt:MouseEvent):void {
+				SpellUI.enableSpelling(halo1, "usa.zwl");
+				SpellUI.enableSpelling(halo2, "usa.zwl");
+				SpellUI.enableSpelling(halo3, "usa.zwl");
+				SpellUI.enableSpelling(spark1, "usa.zwl");
+				SpellUI.enableSpelling(spark2, "usa.zwl");
+				
+			}
+			
+			private function DisableAll(evt:MouseEvent):void {
+				SpellUI.disableSpelling(halo1);
+				SpellUI.disableSpelling(halo2);
+				SpellUI.disableSpelling(halo3);
+				SpellUI.disableSpelling(spark1);
+				SpellUI.disableSpelling(spark2);
+			}
+			
+		]]>
+	</fx:Script>
+	
+	<mx:Label text="Squiggly Spell Checker Flex Demo v0.2" fontSize="30"/>
+	<s:HGroup>
+		<s:Button label="EnableSpelling" click="EnableAll(event)"/>	
+		<s:Button label="DisableSpelling" click="DisableAll(event)"/>		
+	</s:HGroup>
+	
+	<s:HGroup width="100%" height="100%">
+		<s:VGroup width="50%" height="100%">
+			<mx:Label fontSize="30" text="Halo Components"/>
+			<mx:TextInput id="halo1" width="80%" fontSize="30" text="Spell cheecking in halo TextInput"/>
+			<mx:TextArea id="halo2" width="80%" height="50%" fontSize="30" text="Spell cheecking in halo TextArea"/>
+			<mx:RichTextEditor id="halo3" width="80%" height="50%" fontSize="30" text="Spell cheecking in halo RichTextEditor"/>
+		</s:VGroup>
+		<s:VGroup width="50%" height="100%">
+			<mx:Label fontSize="30" text="Spark Components"/>
+			<s:TextInput id="spark1" width="80%" fontSize="30" text="Spell cheecking in spark TextInput"/>
+			<s:TextArea id="spark2" width="80%" height="50%" fontSize="30" text="Spell cheecking in spark TextArea"/>
+		</s:VGroup>
+	</s:HGroup>
+</s:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingConfig.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingConfig.xml b/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingConfig.xml
new file mode 100644
index 0000000..4b2a819
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingConfig.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!--
+
+  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.
+
+-->
+<SpellingConfig>
+  <LanguageResource language="English" languageCode="en_US" ruleFile="data/en_US.aff" dictionaryFile="data/en_US.dic"/>
+  <LanguageResource language="Spanish" languageCode="es_ES" ruleFile="data/es_ES.aff" dictionaryFile="data/es_ES.dic"/>
+  <LanguageResource language="Portuguese" languageCode="pt_PT" ruleFile="data/pt_PT.aff" dictionaryFile="data/pt_PT.dic"/>
+  <LanguageResource language="Italian" languageCode="it_IT" ruleFile="data/it_IT.aff" dictionaryFile="data/it_IT.dic"/>
+  <LanguageResource language="French" languageCode="fr_FR" ruleFile="data/fr_FR.aff" dictionaryFile="data/fr_FR.dic"/>
+</SpellingConfig>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingDemo.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingDemo.mxml b/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingDemo.mxml
new file mode 100644
index 0000000..462c8e9
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingDemo/src/AdobeSpellingDemo.mxml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html" applicationComplete="init()">		
+			<mx:Script>
+			<![CDATA[
+				import com.adobe.linguistics.spelling.SpellUI;
+				import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+				import com.adobe.linguistics.spelling.framework.ResourceTable;
+				
+				
+				public function init():void
+				{
+					var resourceTable:ResourceTable = new ResourceTable();
+					resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});
+					resourceTable.setResource("es_ES", {rule:"data/es_ES.aff", dict:"data/es_ES.dic"});
+					resourceTable.setResource("it_IT", {rule:"data/it_IT.aff", dict:"data/it_IT.dic"});
+					resourceTable.setResource("pt_PT", {rule:"data/pt_PT.aff", dict:"data/pt_PT.dic"});	
+					resourceTable.setResource("fr_FR", {rule:"data/fr_FR.aff", dict:"data/fr_FR.dic"});
+					SpellingConfiguration.resourceTable = resourceTable;
+				}
+			]]>
+    		</mx:Script>
+    		
+			<mx:Label text="Squiggly Spell Checker Flex Demo v0.6" fontSize="30"/>
+
+    		<mx:TabNavigator width="60%" height="100%" fontSize="20">
+    		    <mx:Canvas label="English" width="100%" height="100%">
+    		    	<mx:TextArea id="ta_en" width="100%" height="100%" 
+    		    		text="I know Enlish. Use the context menu to see the suggestions of the missbelled word. "
+    		    		creationComplete="SpellUI.enableSpelling(ta_en, 'en_US');"/>
+    		    </mx:Canvas>
+    		    <mx:Canvas label="Spanish" width="100%" height="100%">
+    		    	<mx:TextArea id="ta_es" width="100%" height="100%" 
+    		    		text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita. "
+    		    		creationComplete="SpellUI.enableSpelling(ta_es, 'es_ES');" />
+    		    </mx:Canvas>
+    		    <mx:Canvas label="Portuguese" width="100%" height="100%">
+    		    	<mx:TextArea id="ta_pt" width="100%" height="100%" 
+    		    		text="Eu sei Portoguês. Use o menu de contexto para ver as sugestões da palavra grafada incorectamente."
+    		    		creationComplete="SpellUI.enableSpelling(ta_pt, 'pt_PT');"/>
+    		    </mx:Canvas>	
+    		    <mx:Canvas label="Italian" width="100%" height="100%">
+    		    	<mx:TextArea id="ta_it" width="100%" height="100%" 
+    		    		text="So italianou. Utilizzare il menu di scelta rapida per visualizzare le suggestioni della parola erreta. "
+    		    		creationComplete="SpellUI.enableSpelling(ta_it, 'it_IT');" />
+    		    </mx:Canvas> 		
+				<mx:Canvas label="French" width="100%" height="100%">
+					<mx:TextArea id="ta_fr" width="100%" height="100%" 
+								 text="Je sais que le frnçais. Utilisez le menu contextuel pour voir les suggestions du mot mal orthogrrraphié. "
+								 creationComplete="SpellUI.enableSpelling(ta_fr, 'fr_FR');" />
+				</mx:Canvas>
+    		</mx:TabNavigator>	
+</mx:Application>
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingConfig.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingConfig.xml b/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingConfig.xml
new file mode 100644
index 0000000..7386b63
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingConfig.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!--
+
+  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.
+
+-->
+<SpellingConfig>
+  <LanguageResource language="English" languageCode="en_US" ruleFile="data/en_US.aff" dictionaryFile="data/en_US.dic"/>
+  <LanguageResource language="Spanish" languageCode="es_ES" ruleFile="data/es_ES.aff" dictionaryFile="data/es_ES.dic"/>
+  <LanguageResource language="Portuguese" languageCode="pt_PT" ruleFile="data/pt_PT.aff" dictionaryFile="data/pt_PT.dic"/>
+  <LanguageResource language="Portuguese(Brazil)" languageCode="pt_BR" ruleFile="data/pt_BR.aff" dictionaryFile="data/pt_BR.dic"/>  
+  <LanguageResource language="Italian" languageCode="it_IT" ruleFile="data/it_IT.aff" dictionaryFile="data/it_IT.dic"/>
+  <LanguageResource language="Romanian" languageCode="ro_RO" ruleFile="data/ro_RO.aff" dictionaryFile="data/ro_RO.dic"/>
+</SpellingConfig>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingDemoEx.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingDemoEx.mxml b/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingDemoEx.mxml
new file mode 100644
index 0000000..9badc49
--- /dev/null
+++ b/Squiggly/main/Demo/AdobeSpellingDemoEx/src/AdobeSpellingDemoEx.mxml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!-- Simple example to demonstrate the Spark TextArea control. -->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
+			   xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" viewSourceURL="srcview/index.html" applicationComplete="init()">
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;
+			import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+			import com.adobe.linguistics.spelling.framework.ResourceTable;
+			
+			
+			public function init():void
+			{
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});
+				resourceTable.setResource("es_ES", {rule:"data/es_ES.aff", dict:"data/es_ES.dic"});
+				resourceTable.setResource("it_IT", {rule:"data/it_IT.aff", dict:"data/it_IT.dic"});
+				resourceTable.setResource("pt_PT", {rule:"data/pt_PT.aff", dict:"data/pt_PT.dic"});	
+				SpellingConfiguration.resourceTable = resourceTable;
+			}
+		]]>
+	</fx:Script>
+	
+	<mx:Label text="Squiggly Spell Checker Flex Demo v0.3" fontSize="30"/>
+	
+	<mx:TabNavigator width="70%" height="100%" fontSize="25">
+		<s:NavigatorContent label="English" width="100%" height="100%">
+			<s:TextArea id="ta_en" width="100%" height="100%" 
+						 text="I know Enlish. Use the context menu to see the suggestions of the missbelled word. "
+						 creationComplete="SpellUI.enableSpelling(ta_en, 'en_US');"/>
+		</s:NavigatorContent>
+		<s:NavigatorContent label="Spanish" width="100%" height="100%">
+			<s:TextArea id="ta_es" width="100%" height="100%" 
+						 text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita. "
+						 creationComplete="SpellUI.enableSpelling(ta_es, 'es_ES');" />
+		</s:NavigatorContent>
+		<s:NavigatorContent label="Portuguese" width="100%" height="100%">
+			<s:TextArea id="ta_pt" width="100%" height="100%" 
+						 text="Eu sei Portoguês. Use o menu de contexto para ver as sugestões da palavra grafada incorectamente."
+						 creationComplete="SpellUI.enableSpelling(ta_pt, 'pt_PT');"/>
+		</s:NavigatorContent>	
+		<s:NavigatorContent label="Italian" width="100%" height="100%">
+			<s:TextArea id="ta_it" width="100%" height="100%" 
+						 text="So italianou. Utilizzare il menu di scelta rapida per visualizzare le suggestioni della parola erreta. "
+						 creationComplete="SpellUI.enableSpelling(ta_it, 'it_IT');"/>
+		</s:NavigatorContent>
+	</mx:TabNavigator>
+</s:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/README.txt
----------------------------------------------------------------------
diff --git a/Squiggly/main/README.txt b/Squiggly/main/README.txt
new file mode 100644
index 0000000..00b9745
--- /dev/null
+++ b/Squiggly/main/README.txt
@@ -0,0 +1,28 @@
+How to use the Squiggly SDK
+===================================
+
+Please read the ASDoc first to understand the classes in Squiggly.
+
+If you are using the SpellChecker class directly, you need.
+- AdobeSpellingEngine.swc in [YourProject]/libs folder, you can find it from ./libs
+- Dictionary files in [YourProject]/src folder, your can find them from ./src/dictionaries folder
+
+If you are using the simple UI integration feature (SpellUI class), in addition to what mentioned above, you also need
+- AdobeSpellingConfig.xml in [YourProject]/src
+- AdobeSpellingUI.swc (AdobeSpellingUIEx.swc if you need spark support in Flex 4) in [YourProject]/libs 
+
+This SDK came with English(US) dictionary. You can download additional HunSpell dictionaries, but for now, what we have tested are just English, Spanish, Portuguese and Italian. If you are doing this, you need to understand AdobeSpellingConfig.xml.
+
+Here's the content of AdobeSpellingConfig.xml, each entry maps the languageCode with the relative path for resource files. 
+<SpellingConfig>
+  <LanguageResource language="English" languageCode="en_US" ruleFile="dictionaries/en_US/en_US.aff" dictionaryFile="dictionaries/en_US/en_US.dic"/>
+</SpellingConfig>
+
+So if you are adding Spanish, you just need to get the hunspell dictionary es_ES.aff/dic and add one line to your config file.
+  <LanguageResource language="Spanish" languageCode="es_ES" ruleFile="dictionaries/es_ES/es_ES.aff" dictionaryFile="dictionaries/es_ES/es_ES.dic"/>
+
+Note that you can put the dictionaries in another location as long as you update the config file, the config file itself MUST be in [YourProject]/src folder.
+
+
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/AdobeSpellingDictGen/README.txt
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/AdobeSpellingDictGen/README.txt b/Squiggly/main/Tools/AdobeSpellingDictGen/README.txt
new file mode 100644
index 0000000..5326ed6
--- /dev/null
+++ b/Squiggly/main/Tools/AdobeSpellingDictGen/README.txt
@@ -0,0 +1,16 @@
+Squiggly Dictionary Generator v0.1
+
+README
+===================================
+
+This is a simple AIR application that converts a plain text word list file to an Adobe Spelling Dictionary file. 
+
+Here's what each step is doing:
+1. Load a plain text file, each line in the file contains one word, a sampleWOrdList.txt is provided
+2. Calculate the metaphone, which will improve spell checker performance and result
+3. Generate a Squiggly Dictionary object
+4. Export the the Squiggly Dictionary object to a compressed binary file (recommend using *.zwl extension)
+
+Once you have the zwl file, you can use it in your Flex/AIR project.
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/AdobeSpellingDictGen/sample/sampleWordList.txt
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/AdobeSpellingDictGen/sample/sampleWordList.txt b/Squiggly/main/Tools/AdobeSpellingDictGen/sample/sampleWordList.txt
new file mode 100644
index 0000000..3c6e8ce
--- /dev/null
+++ b/Squiggly/main/Tools/AdobeSpellingDictGen/sample/sampleWordList.txt
@@ -0,0 +1,13 @@
+adobe
+apple
+amazon
+microsoft
+intel
+ibm
+google
+yahoo
+ebay
+vmware
+sun
+orcale
+facebook
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen-app.xml b/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen-app.xml
new file mode 100644
index 0000000..ecff5e3
--- /dev/null
+++ b/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen-app.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 
+ 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.
+ 
+ -->
+<application xmlns="http://ns.adobe.com/air/application/1.5">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- The application identifier string, unique to this application. Required. -->
+	<id>AdobeSpellingDictGen</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>AdobeSpellingDictGen</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>AdobeSpellingDictGen</name>
+
+	<!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
+	<version>v1</version>
+
+	<!-- Description, displayed in the AIR application installer.
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flex Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flex Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+	</initialWindow>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+		 specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image48x48></image48x48>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen.mxml b/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen.mxml
new file mode 100644
index 0000000..2399910
--- /dev/null
+++ b/Squiggly/main/Tools/AdobeSpellingDictGen/src/AdobeSpellingDictGen.mxml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="800" height="600" fontSize="12">
+
+
+	<mx:Script>
+		<![CDATA[
+			
+			import com.adobe.linguistics.spelling.utils.WordList;
+			import com.adobe.linguistics.spelling.engine.dictionary.SuseDictionary;
+			import com.adobe.linguistics.spelling.codec.language.MetaPhone;
+			
+			// For debug only
+			private var tsStart:int
+			private var tsEnd:int;
+			
+			// An array with words only
+			private var basicWordList:Array;
+			
+			// A suse dictionary object (hash) as defined in suse engine
+			private var suse:SuseDictionary;
+			
+			// An array with index, word, metaphone
+			[Bindable]
+			private var advWordList:Array;
+			
+			private var src:File = File.applicationDirectory;
+			private var dest:File = File.applicationDirectory;
+			
+			
+			private function browseInFile():void
+			{
+				try {
+					src.browseForOpen("Select a TXT file");
+					src.addEventListener(Event.SELECT, inFileSelected);
+				} catch (error:Error)
+				{
+					trace("Failed:", error.message);
+				}
+			}
+			
+			private function inFileSelected(event:Event):void
+			{	
+				tsStart = getTimer();
+				var file:File = event.target as File;
+				var stream:FileStream = new FileStream();
+				stream.open(file, FileMode.READ);
+				var fileData:String = stream.readUTFBytes(stream.bytesAvailable);
+				
+				if (fileData.charAt(fileData.indexOf("\n")-2) == "\r")		//Strange, but happened when generating the text file from mac
+				{
+					basicWordList = fileData.split("\r\r\n");
+				}
+				else if (fileData.charAt(fileData.indexOf("\n")-1) == "\r")
+				{
+					basicWordList = fileData.split("\r\n");			//Windows
+				}
+				else 
+				{
+					basicWordList = fileData.split("\n");			//Mac and linux
+				}
+				
+				loadTxtInfo.text = file.nativePath + " (" + basicWordList.length.toString() + " words, " + file.size.toString() + " bytes)";
+				loadTxtInfo.setStyle("color", "green");
+				
+				// Debug log
+				tsEnd = getTimer();
+				debugInfo.text += "DebugInfo\n================\n" + "TxtLoaded: "+ file.nativePath + " " + (tsEnd - tsStart).toString() + "ms" + "\n";
+				prepareToShow();
+			}
+			
+			
+			private function browseOutFile():void
+			{
+				try {
+					dest.browseForSave("Output ZWL file");
+					dest.addEventListener(Event.SELECT, outFileSelected);
+				} catch (error:Error)
+				{
+					trace("Failed:", error.message);
+				}
+			}
+			
+			private function outFileSelected(event:Event):void
+			{				
+				tsStart = getTimer();
+				var bytes:ByteArray = new ByteArray();
+	    		bytes.writeObject(suse);
+	    		bytes.position = 0;
+	    		bytes.compress();
+	    		bytes.position = 0;
+	    		var outFile:File = new File((event.target as File).nativePath);
+	    		var outStream:FileStream = new FileStream();
+	    		outStream.open(outFile, FileMode.WRITE);
+	    		outStream.writeBytes(bytes, 0, bytes.length);
+	    		outStream.close();
+	    		
+	    		exportInfo.text = outFile.nativePath + " (" + outFile.size.toString() + " bytes)";
+				exportInfo.setStyle("color", "green");
+				
+				// Debug log
+	    		tsEnd = getTimer();
+	    		debugInfo.text += "\nZwlExported: " + outFile.nativePath + " " + (tsEnd - tsStart).toString() + "ms\n";
+				
+			}
+			
+	
+			
+			private function prepareToShow():void
+			{
+				
+				advWordList = new Array();
+				for (var i:uint=0; i<basicWordList.length; i++) {
+					// In case some empty string are there
+					if (basicWordList[i] != "")
+						advWordList.push(new UIWord(i, basicWordList[i]));
+				}
+			}
+			
+			private function genMeta():void
+			{
+
+				var _metaphone:MetaPhone= new MetaPhone();
+				tsStart = getTimer();
+				for (var i:uint=0; i<advWordList.length; i++) {
+					advWordList[i].meta = _metaphone.meta(advWordList[i].word, 4);
+				}
+				genMetaInfo.text = "Metaphone index generated";
+				genMetaInfo.setStyle("color", "green");
+				myDataGrid.dataProvider= advWordList;
+				// Debug log
+				tsEnd = getTimer();
+				debugInfo.text += "\nMetaGenerated: " + (tsEnd - tsStart).toString() + "ms\n";
+			}
+			
+			private function genSuseDict():void
+			{
+				suse = new SuseDictionary();
+				tsStart = getTimer();
+				for (var i:uint=0; i<advWordList.length; i++) {
+					if (suse.MetaPhoneHash[advWordList[i].meta]) {
+						suse.MetaPhoneHash[advWordList[i].meta].insert(advWordList[i].word);
+					}
+					else {
+						if ((advWordList[i].meta == "") || (advWordList[i].meta == "-nde")) continue;
+						suse.MetaPhoneHash[advWordList[i].meta] = new WordList();
+						suse.MetaPhoneHash[advWordList[i].meta].insert(advWordList[i].word);
+					}
+				}
+				genDictInfo.text = "SquigglyDict object generated";
+				genDictInfo.setStyle("color", "green");
+				
+				// Debug log
+				tsEnd = getTimer();
+				debugInfo.text += "\nSquigglyDictGenerated: " + (tsEnd - tsStart).toString() + "ms\n"; 	
+			}
+			
+		]]>
+	</mx:Script>
+	<mx:HBox width="100%">
+		<mx:Label text="Squiggly Dictionary Generator v0.1 (txt2zwl)" fontSize="25"/>		
+	</mx:HBox>
+	<mx:HBox width="100%">
+		<mx:Button label="1. Load TXT File" click="browseInFile()"/>
+		<mx:HRule visible="false" width="100%"/>
+		<mx:Label id="loadTxtInfo" text="Not loaded" color="red"/>
+	</mx:HBox>
+	<mx:HBox width="100%">
+		<mx:Button label="2. Calculate Metaphone" click="genMeta()"/>
+		<mx:HRule visible="false" width="100%"/>
+		<mx:Label id="genMetaInfo" text="Not calculated" color="red"/>
+	</mx:HBox>
+	<mx:HBox width="100%">
+		<mx:Button label="3. Generate SquigglyDict" click="genSuseDict()"/>		
+		<mx:HRule visible="false" width="100%"/>
+		<mx:Label id="genDictInfo" text="Not generated" color="red"/>
+	</mx:HBox>
+	<mx:HBox width="100%">
+		<mx:Button label="4. Export ZWL File" click = "browseOutFile()"/>
+		<mx:HRule visible="false" width="100%"/>
+		<mx:Label id="exportInfo" text="Not exported" color="red"/>
+	</mx:HBox>
+	<mx:HBox width="100%" height="100%">
+		<mx:DataGrid height="100%" id="myDataGrid" dataProvider = "{ advWordList }" width="70%">
+			<mx:columns>
+				<mx:DataGridColumn headerText="Index" dataField="index"/>
+				<mx:DataGridColumn headerText="Word" dataField="word"/>
+				<mx:DataGridColumn headerText="Metaphone" dataField="meta"/>
+			</mx:columns>
+		</mx:DataGrid>
+		<mx:TextArea id="debugInfo" height="100%" width="30%" />
+	</mx:HBox>
+</mx:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/AdobeSpellingDictGen/src/UIWord.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/AdobeSpellingDictGen/src/UIWord.as b/Squiggly/main/Tools/AdobeSpellingDictGen/src/UIWord.as
new file mode 100644
index 0000000..74c32e5
--- /dev/null
+++ b/Squiggly/main/Tools/AdobeSpellingDictGen/src/UIWord.as
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+	public class UIWord
+	{
+		public var index:uint;
+		public var word:String;
+		public var meta:String;
+		
+		public function UIWord(inIndex:uint, inWord:String)
+		{
+			index = inIndex;
+			word = inWord;
+			meta = "";
+		}
+	
+	}
+	
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Tools/performanceTool/src/performanceTool.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/Tools/performanceTool/src/performanceTool.mxml b/Squiggly/main/Tools/performanceTool/src/performanceTool.mxml
new file mode 100644
index 0000000..30b629d
--- /dev/null
+++ b/Squiggly/main/Tools/performanceTool/src/performanceTool.mxml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" horizontalAlign="left">
+<mx:Script>
+	<![CDATA[
+		import com.adobe.linguistics.spelling.*;
+		import mx.controls.textClasses.TextRange;
+		
+		private var _newdict:SpellingDictionary = new SpellingDictionary();
+		private var sp:SpellChecker= new SpellChecker();
+		private function init():void {
+			_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+			var myUrl:URLRequest = new URLRequest("usa.zwl");
+			_newdict.load(myUrl);
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp.addDictionary(_newdict);
+		}
+
+		private function checkText():void {
+			var wordPattern:RegExp =/\b\w+\b/; // match next word...
+			var inputValue:String = inputText.text;
+			var rangeArray:Array = new Array();
+			var wordArray:Array = new Array();
+			var offset:int, curPos:int;
+			for ( ; ; ) {
+				var res:Array = inputValue.match( wordPattern); // lookup word by word....
+				if ( res == null ) break;
+				offset = inputText.text.length-inputValue.length;
+				curPos = inputValue.indexOf(res[0]);
+				var currentRange:TextRange = new TextRange(inputText, false, offset+ curPos, offset+ curPos+res[0].length); // mark mispelled word.
+				wordArray.push( res[0] );
+				rangeArray.push( currentRange );
+				inputValue = inputValue.substr(inputValue.indexOf(res[0])+ res[0].length);
+			}
+	        var nStart:Number;
+	        var nMillisElapsed:Number;
+	        var totalMispelled:int = 0;
+			nStart = new Date().time;
+			for ( var i:int=0; i< wordArray.length ; i++ ) {
+				if ( !sp.checkWord( wordArray[i] ) ) {
+					totalMispelled++;
+				}
+			}
+			nMillisElapsed  = new Date().time - nStart;
+			outputText.text = "Total "+ wordArray.length + " Words.\n" + 
+			"Total " + totalMispelled + " Mispelled Words.\n" +
+			"Mispell Rate:" + (totalMispelled/wordArray.length) + ".\n" +
+			"Total time(ms):" + nMillisElapsed + "ms.\n" +
+			"Performance Result:" + (wordArray.length/nMillisElapsed)*1000 + " words per second.\n";
+			for ( i=0; i< wordArray.length ; i++ ) {
+				if ( !sp.checkWord( wordArray[i] ) ) {
+					rangeArray[i].color = "red";
+				}
+			}
+			
+		}
+		
+	]]>
+</mx:Script>
+	<mx:HBox>
+		<mx:Button id="check" label="Check Text" click="checkText()"  />
+	</mx:HBox>
+	<mx:TextArea id="inputText" height="100%" width="100%"/>	
+	<mx:TextArea id="outputText" height="10%" width="50%" editable="false" backgroundColor="0xffcc00"/>	
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/build.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/build.xml b/Squiggly/main/build.xml
new file mode 100644
index 0000000..5bae583
--- /dev/null
+++ b/Squiggly/main/build.xml
@@ -0,0 +1,231 @@
+<?xml version="1.0" ?>
+<!--
+
+  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.
+
+-->
+<project default="test" basedir=".">
+
+    <property file="${basedir}/env.properties"/>
+    <property environment="env"/>
+    <property file="${basedir}/local.properties"/>
+    <property file="${basedir}/build.properties"/>
+    <condition property="FLEX_HOME" value="${env.FLEX_HOME}">
+        <isset property="env.FLEX_HOME" />
+    </condition>
+    <condition property="AIR_HOME" value="${env.AIR_HOME}">
+        <isset property="env.AIR_HOME" />
+    </condition>
+    <condition property="PLAYERGLOBAL_HOME" value="${env.PLAYERGLOBAL_HOME}">
+        <isset property="env.PLAYERGLOBAL_HOME" />
+    </condition>
+
+    <!-- SDK properties -->
+    <property name="FLEX_HOME" value="C:/air3_beta2"/>
+    <property name="AIR_HOME" value="C:/air3_beta2"/>
+	<property name="MXMLC.JAR" value="${FLEX_HOME}/lib/mxmlc.jar"/>
+	<property name="COMPC.JAR" value="${FLEX_HOME}/lib/compc.jar"/>
+	<property name="ADL" value="${AIR_HOME}/bin/adl.exe"/>
+    <property name="ADT.JAR" value="${AIR_HOME}/lib/adt.jar"/>
+    <property name="playerglobal.version" value="11.1" />
+	
+    <property name="OUTPUT_DIR" value="libs"/>
+    
+     <target name="init" depends="clean">
+     	<mkdir dir="${OUTPUT_DIR}"/>
+    </target>
+	
+	<target name="compilelinguistics" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeLinguisticUtils/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeLinguisticUtils/src"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+		</java>
+	</target>
+	
+	<target name="compileengine" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingEngine/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingEngine/src"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+		</java>
+	</target>
+
+	<target name="compileframework" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingFramework/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingFramework/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/framework.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/mx/mx.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/spark.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/textLayout.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+		</java>
+	</target>
+
+	<target name="compileui" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingUI/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingUI/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/framework.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/mx/mx.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/spark.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/textLayout.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingUI.swc"/>
+		</java>
+	</target>
+
+    <target name="compileuiapi" depends="init">
+        <java jar="${COMPC.JAR}" fork="true" failonerror="true">
+            <arg value="-swf-version"/>
+            <arg value="13"/>
+            <arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+            <arg value="-source-path"/>
+            <arg value="AdobeSpellingUIAPI/src"/>
+            <arg value="-include-sources"/>
+            <arg value="AdobeSpellingUIAPI/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/framework.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/mx/mx.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/spark.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/textLayout.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+            <arg value="-output"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingUIAPI.swc"/>
+        </java>
+    </target>
+
+    <target name="compileuitlf" depends="init">
+        <java jar="${COMPC.JAR}" fork="true" failonerror="true">
+            <arg value="-swf-version"/>
+            <arg value="13"/>
+            <arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+            <arg value="-source-path"/>
+            <arg value="AdobeSpellingUITLF/src"/>
+            <arg value="-include-sources"/>
+            <arg value="AdobeSpellingUITLF/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/textLayout.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingUI.swc"/>
+            <arg value="-output"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingUITLF.swc"/>
+        </java>
+    </target>
+
+    <target name="compileuiex" depends="init">
+        <java jar="${COMPC.JAR}" fork="true" failonerror="true">
+            <arg value="-swf-version"/>
+            <arg value="13"/>
+            <arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+            <arg value="-source-path"/>
+            <arg value="AdobeSpellingUIEx/src"/>
+            <arg value="-include-sources"/>
+            <arg value="AdobeSpellingUIEx/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/framework.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/mx/mx.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/spark.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${FLEX_HOME}/frameworks/libs/textLayout.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+            <arg value="-external-library-path"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingUI.swc"/>
+            <arg value="-output"/>
+            <arg value="${OUTPUT_DIR}/AdobeSpellingUIEx.swc"/>
+        </java>
+    </target>
+
+    <target name="test" depends="compilelinguistics, compileengine, compileframework, compileui, compileuiapi, compileuitlf, compileuiex">
+    </target>
+   
+    <target name="clean" description="clean up">
+    	<delete dir="${OUTPUT_DIR}"/>
+    </target>
+</project>
\ No newline at end of file


[18/18] git commit: [flex-utilities] [refs/heads/develop] - Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
Squiggly spell checker donation from Adobe Systems Inc.


Project: http://git-wip-us.apache.org/repos/asf/flex-utilities/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-utilities/commit/a52655ac
Tree: http://git-wip-us.apache.org/repos/asf/flex-utilities/tree/a52655ac
Diff: http://git-wip-us.apache.org/repos/asf/flex-utilities/diff/a52655ac

Branch: refs/heads/develop
Commit: a52655acc312c73c97f7900e0f5ce2adaaa760cc
Parents: e3d2737
Author: Alex Harui <ah...@apache.org>
Authored: Thu Apr 24 22:25:34 2014 -0700
Committer: Alex Harui <ah...@apache.org>
Committed: Thu Apr 24 22:26:52 2014 -0700

----------------------------------------------------------------------
 .../src/SquigglyTLFExample.as                   |    44 +
 .../src/UserDictionaryExample-app.xml           |   153 +
 .../src/UserDictionaryExample.mxml              |   126 +
 .../Examples/Flex/CheckWord/src/CheckWord.mxml  |    47 +
 .../Flex/ConfigExample/src/ConfigExample.mxml   |    61 +
 .../locale/en_US/SquigglyContextMenu.properties |    23 +
 .../locale/es_ES/SquigglyContextMenu.properties |    23 +
 .../src/ContextMenuWithResource.mxml            |    60 +
 .../src/CustomContextMenu.mxml                  |    40 +
 .../Flex/GetSuggestion/src/GetSuggestion.mxml   |    60 +
 .../src/SpellingServiceEsg.mxml                 |    80 +
 .../src/SquigglyUIExample.mxml                  |    40 +
 .../Flex/TextEditor/src/TextEditor.mxml         |    61 +
 Squiggly/ane/Examples/HowToUseExamples.txt      |    34 +
 .../HunspellNativeExtension/EncConv.cpp         |   294 +
 .../HunspellNativeExtension/EncConv.h           |    59 +
 .../English.lproj/InfoPlist.strings             |     2 +
 .../HunspellNativeExtension/Exported_Sym_FIle   |     4 +
 .../HunspellNativeExtension.cpp                 |   368 +
 .../HunspellNativeExtension.h                   |    37 +
 .../project-sve.pbxproj                         |   329 +
 .../project.pbxproj                             |   428 +
 .../contents.xcworkspacedata                    |    25 +
 .../HunspellNativeExtension/Info.plist          |    46 +
 .../HunspellNativeExtension/Utilities.cpp       |    20 +
 .../HunspellNativeExtension/Utilities.h         |    41 +
 .../HunspellNativeExtension/create_fw.sh        |    39 +
 Squiggly/ane/README.txt                         |    28 +
 Squiggly/ane/SWCandANE/build.properties         |    32 +
 Squiggly/ane/SWCandANE/build.xml                |   210 +
 Squiggly/ane/SWCandANE/create_ane.sh            |    68 +
 Squiggly/ane/SWCandANE/create_swc.sh            |    38 +
 .../ane/SWCandANE/extensions/src/extension.xml  |    38 +
 .../src/HunspellNativeExtensionWorkflow-app.xml |   244 +
 .../src/HunspellNativeExtensionWorkflow.mxml    |   123 +
 .../extensions/HunspellNativeExtension.as       |   128 +
 .../com/adobe/linguistics/utils/ITokenizer.as   |    82 +
 .../com/adobe/linguistics/utils/TextFilter.as   |    90 +
 .../adobe/linguistics/utils/TextTokenizer.as    |   400 +
 .../src/com/adobe/linguistics/utils/Token.as    |    95 +
 .../linguistics/spelling/UserDictionary.as      |   173 +
 .../spelling/UserDictionaryInternal.as          |   120 +
 .../spelling/core/UserDictionaryEngine.as       |    75 +
 .../linguistics/spelling/utils/WordList.as      |   128 +
 .../AdobeSpellingFramework/asdocgen.bat         |    18 +
 .../spelling/framework/ResourceTable.as         |   143 +
 .../spelling/framework/SpellingConfiguration.as |   103 +
 .../spelling/framework/SpellingService.as       |   223 +
 .../spelling/framework/UserDictionaryV.as       |   113 +
 .../adobe/linguistics/spelling/SpellUIForTLF.as |   597 +
 .../linguistics/spelling/ui/IHighlighter.as     |    67 +
 .../linguistics/spelling/ui/IWordProcessor.as   |    32 +
 .../linguistics/spelling/ui/TLFHighlighter.as   |   252 +
 .../linguistics/spelling/ui/TLFWordProcessor.as |   164 +
 .../Squiggly/Demo/SimpleEditor/SimpleText.xml   |    23 +
 .../SimpleEditor/src/AdobeSpellingConfig.xml    |    22 +
 .../SimpleEditor/src/MyContainerController.as   |   300 +
 .../Demo/SimpleEditor/src/SimpleEditor-app.xml  |   253 +
 .../Demo/SimpleEditor/src/SimpleEditor.mxml     |    82 +
 .../SimpleEditor/src/SimpleEditorPanel.mxml     |   393 +
 Squiggly/ane/Squiggly/build.xml                 |   131 +
 .../HunspellNativeExtension.sln                 |    26 +
 .../HunspellNativeExtension/CharConv.cpp        |   130 +
 .../HunspellNativeExtension/CharConv.h          |    71 +
 .../HunspellNativeExtension/EncConv.cpp         |   281 +
 .../HunspellNativeExtension/EncConv.h           |    56 +
 .../HunspellNativeExtension.cpp                 |   334 +
 .../HunspellNativeExtension.h                   |    54 +
 .../HunspellNativeExtension.vcxproj             |   194 +
 .../HunspellNativeExtension/resource.h          |    22 +
 .../HunspellNativeExtension/win/Utilities.h     |   118 +
 Squiggly/ane/build.xml                          |    31 +
 .../src/SquigglyTLFExample.as                   |    59 +
 .../src/UserDictionaryExample-app.xml           |   153 +
 .../src/UserDictionaryExample.mxml              |   132 +
 .../Examples/Flex/CheckWord/src/CheckWord.mxml  |    68 +
 .../Flex/ConfigExample/src/ConfigExample.mxml   |    77 +
 .../locale/en_US/SquigglyContextMenu.properties |    19 +
 .../locale/es_ES/SquigglyContextMenu.properties |    19 +
 .../src/ContextMenuWithResource.mxml            |    74 +
 .../src/CustomContextMenu.mxml                  |    59 +
 .../Flex/GetSuggestion/src/GetSuggestion.mxml   |    84 +
 .../src/SpellingServiceEsg.mxml                 |    98 +
 .../src/AdobeSpellingFrameworkExample.mxml      |    80 +
 .../src/SquigglyUIExample.mxml                  |    55 +
 .../src/SquigglyUIexampleDictload.mxml          |    79 +
 .../src/SquigglyUIexampleUBS.mxml               |   596 +
 .../Flex/TextEditor/src/TextEditor.mxml         |    83 +
 .../spelling/Examples/HowToUseExamples.txt      |    33 +
 .../com/adobe/linguistics/utils/ITokenizer.as   |    76 +
 .../adobe/linguistics/utils/TextTokenizer.as    |   393 +
 .../src/com/adobe/linguistics/utils/Token.as    |    94 +
 .../linguistics/spelling/HunspellDictionary.as  |   205 +
 .../adobe/linguistics/spelling/ISpellChecker.as |    62 +
 .../linguistics/spelling/ISpellingDictionary.as |    45 +
 .../adobe/linguistics/spelling/SpellChecker.as  |   387 +
 .../linguistics/spelling/UserDictionary.as      |   113 +
 .../spelling/UserDictionaryInternal.as          |   115 +
 .../spelling/core/DictionaryManager.as          |    73 +
 .../linguistics/spelling/core/HashEntry.as      |   108 +
 .../linguistics/spelling/core/LinguisticRule.as |  1118 +
 .../linguistics/spelling/core/SpellingInfo.as   |    32 +
 .../spelling/core/SquigglyDictionary.as         |   207 +
 .../linguistics/spelling/core/SquigglyEngine.as |   426 +
 .../spelling/core/SuggestionManager.as          |  1026 +
 .../spelling/core/UserDictionaryEngine.as       |    71 +
 .../spelling/core/container/Collection.as       |    89 +
 .../spelling/core/container/Enumeration.as      |    28 +
 .../spelling/core/container/HashTable.as        |   179 +
 .../linguistics/spelling/core/container/Heap.as |   263 +
 .../spelling/core/container/Iterator.as         |    64 +
 .../linguistics/spelling/core/container/Set.as  |   195 +
 .../spelling/core/container/SparseHashTable.as  |   283 +
 .../spelling/core/env/ExternalConstants.as      |    47 +
 .../spelling/core/env/InternalConstants.as      |    87 +
 .../spelling/core/error/ContentError.as         |    39 +
 .../spelling/core/error/ErrorTable.as           |    41 +
 .../spelling/core/logging/AbstractTarget.as     |   167 +
 .../spelling/core/logging/ILogger.as            |    40 +
 .../spelling/core/logging/ILoggingTarget.as     |    39 +
 .../linguistics/spelling/core/logging/Log.as    |   210 +
 .../spelling/core/logging/LogEvent.as           |    87 +
 .../spelling/core/logging/LogEventLevel.as      |    76 +
 .../spelling/core/logging/LogLogger.as          |   102 +
 .../core/logging/targets/ArrayTarget.as         |    35 +
 .../core/logging/targets/CollectionTarget.as    |   107 +
 .../core/logging/targets/LineFormattedTarget.as |   104 +
 .../core/logging/targets/TextFieldTarget.as     |    52 +
 .../core/logging/targets/TraceTarget.as         |    37 +
 .../spelling/core/rule/AffixEntry.as            |   137 +
 .../linguistics/spelling/core/rule/AffixRule.as |    92 +
 .../linguistics/spelling/core/rule/MapFilter.as |    39 +
 .../spelling/core/rule/OptimizedPrefixEntry.as  |   245 +
 .../spelling/core/rule/OptimizedSuffixEntry.as  |   301 +
 .../spelling/core/rule/PrefixEntry.as           |   102 +
 .../spelling/core/rule/ReplacementFilter.as     |    34 +
 .../spelling/core/rule/SimpleFilter.as          |    48 +
 .../spelling/core/rule/SuffixEntry.as           |   126 +
 .../spelling/core/utils/DictionaryLoader.as     |    94 +
 .../spelling/core/utils/LinguisticRuleLoader.as |   977 +
 .../spelling/core/utils/MathUtils.as            |    66 +
 .../spelling/core/utils/RefObject.as            |    36 +
 .../spelling/core/utils/SimpleNumberParser.as   |    54 +
 .../core/utils/SquigglyDictionaryLoader.as      |   369 +
 .../spelling/core/utils/StringUtils.as          |   333 +
 .../spelling/core/utils/SuggestionsResult.as    |   142 +
 .../adobe/linguistics/spelling/utils/Token.as   |    47 +
 .../linguistics/spelling/utils/Tokenizer.as     |    96 +
 .../linguistics/spelling/utils/WordList.as      |   120 +
 .../main/AdobeSpellingFramework/asdocgen.bat    |    18 +
 .../spelling/framework/ResourceTable.as         |   134 +
 .../spelling/framework/SpellingConfiguration.as |   102 +
 .../spelling/framework/SpellingService.as       |   241 +
 .../spelling/framework/ui/HaloHighlighter.as    |   124 +
 .../spelling/framework/ui/HaloWordProcessor.as  |   111 +
 .../spelling/framework/ui/IHighlighter.as       |    34 +
 .../spelling/framework/ui/IWordProcessor.as     |    30 +
 .../spelling/framework/ui/SparkHighlighter.as   |   225 +
 .../spelling/framework/ui/SparkWordProcessor.as |   132 +
 .../framework/ui/SpellingHighlighter.as         |   179 +
 .../spelling/framework/ui/TLFHighlighter.as     |   248 +
 .../spelling/framework/ui/TLFWordProcessor.as   |   156 +
 .../com/adobe/linguistics/spelling/SpellUI.as   |   562 +
 .../linguistics/spelling/SpellingContextMenu.as |   243 +
 .../linguistics/spelling/ui/HaloHighlighter.as  |   126 +
 .../spelling/ui/HaloWordProcessor.as            |   112 +
 .../linguistics/spelling/ui/IHighlighter.as     |    67 +
 .../linguistics/spelling/ui/IWordProcessor.as   |    30 +
 .../linguistics/spelling/ui/SparkHighlighter.as |   229 +
 .../spelling/ui/SparkWordProcessor.as           |   133 +
 .../spelling/ui/SpellingHighlighter.as          |   196 +
 .../linguistics/spelling/ui/TLFHighlighter.as   |   252 +
 .../linguistics/spelling/ui/TLFWordProcessor.as |   159 +
 .../linguistics/spelling/ui/HaloHighlighter.as  |    87 +
 .../spelling/ui/HaloWordProcessor.as            |   109 +
 .../linguistics/spelling/ui/IHighlighter.as     |    34 +
 .../linguistics/spelling/ui/IWordProcessor.as   |    30 +
 .../linguistics/spelling/ui/SparkHighlighter.as |   190 +
 .../spelling/ui/SparkWordProcessor.as           |   104 +
 .../spelling/ui/SpellingHighlighter.as          |   179 +
 .../com/adobe/linguistics/spelling/SpellUI.as   |   577 +
 .../linguistics/spelling/SpellingContextMenu.as |   243 +
 .../adobe/linguistics/spelling/SpellUIForTLF.as |   522 +
 .../spelling/SpellingContextMenuForTLF.as       |   249 +
 .../SquigglyCustomContainerController.as        |   258 +
 Squiggly/main/Automation/asdocgen.bat           |    18 +
 Squiggly/main/Automation/copydictsandlibs.bat   |    35 +
 Squiggly/main/Automation/examplegen.py          |    75 +
 .../main/Automation/prepareReleasePackage.bat   |    20 +
 Squiggly/main/Data/genTextWordlist.sh           |    31 +
 Squiggly/main/Data/usa.txt                      | 97812 +++++++++++++++++
 .../src/AdobeSpellingAirDemo-app.xml            |   153 +
 .../src/AdobeSpellingAirDemo.mxml               |    39 +
 .../src/AdobeSpellingAirDemoEx-app.xml          |   153 +
 .../src/AdobeSpellingAirDemoEx.mxml             |    71 +
 .../src/AdobeSpellingConfig.xml                 |    26 +
 .../src/AdobeSpellingDemo.mxml                  |    72 +
 .../src/AdobeSpellingConfig.xml                 |    27 +
 .../src/AdobeSpellingDemoEx.mxml                |    70 +
 Squiggly/main/README.txt                        |    28 +
 .../main/Tools/AdobeSpellingDictGen/README.txt  |    16 +
 .../sample/sampleWordList.txt                   |    13 +
 .../src/AdobeSpellingDictGen-app.xml            |   153 +
 .../src/AdobeSpellingDictGen.mxml               |   210 +
 .../Tools/AdobeSpellingDictGen/src/UIWord.as    |    37 +
 .../performanceTool/src/performanceTool.mxml    |    84 +
 Squiggly/main/build.xml                         |   231 +
 207 files changed, 126796 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as b/Squiggly/ane/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
new file mode 100644
index 0000000..cad0b92
--- /dev/null
+++ b/Squiggly/ane/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
@@ -0,0 +1,44 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+	import flash.display.Sprite;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.EditManager;
+	
+	import com.adobe.linguistics.spelling.SpellUIForTLF;
+	
+	public class SquigglyTLFExample extends Sprite
+	{
+		public function SquigglyTLFExample()
+		{
+			var markup:XML = <TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p><span>I know &nbsp;</span><span fontStyle='italic'>Enlish</span><span>. Use the context menu to see the suggestions of the missbelled word.</span></p></TextFlow>;
+			var textFlow:TextFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT);
+			textFlow.flowComposer.addController(new ContainerController(this, 500, 600));
+			textFlow.flowComposer.updateAllControllers();
+			
+			textFlow.interactionManager = new EditManager();
+			
+			SpellUIForTLF.enableSpelling(textFlow, "en_US");
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml b/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
new file mode 100644
index 0000000..d400631
--- /dev/null
+++ b/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+<application xmlns="http://ns.adobe.com/air/application/1.5.1">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5.1
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- The application identifier string, unique to this application. Required. -->
+	<id>UserDictionaryExample</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>UserDictionaryExample</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>UserDictionaryExample</name>
+
+	<!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
+	<version>v1</version>
+
+	<!-- Description, displayed in the AIR application installer.
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flex Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flex Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+	</initialWindow>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+		 specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image48x48></image48x48>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml b/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
new file mode 100644
index 0000000..68d32de
--- /dev/null
+++ b/Squiggly/ane/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="left" initialize="init()">
+<mx:Script>
+	<![CDATA[
+
+
+	import com.adobe.linguistics.spelling.HunspellDictionary;
+	import com.adobe.linguistics.spelling.SpellChecker;
+	import com.adobe.linguistics.spelling.UserDictionary;
+		
+	
+	private var ud:UserDictionary;
+	private var _newdict:HunspellDictionary = new HunspellDictionary();
+	private var sp:SpellChecker;
+	private function init():void {
+		_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+		_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+	}
+		
+	private function handleLoadComplete(evt:Event):void
+	{
+		sp = new SpellChecker(_newdict);
+	}
+
+	private function checkWord():void {
+		if( sp.checkWord( inputWord.text ) )
+			result.text = "Result:correct";
+		else
+			result.text = "Result:wrong";
+	}
+		
+	public function updateWordList():void
+	{
+		wordList.text = "";
+		
+		var wl:Vector.<String> = ud.wordList;
+		for each(var w:String in wl)
+		{
+			wordList.text += w + "\n";
+		}
+		
+	}
+	
+	
+	public function loadDict():void
+	{
+		var inFile:File = File.desktopDirectory;
+		inFile = inFile.resolvePath(filename.text);
+		if (inFile.exists)
+		{		
+			var inStream:FileStream = new FileStream();
+			inStream.open(inFile, FileMode.READ);
+			ud = new UserDictionary(inStream.readObject() as Vector.<String>);
+			inStream.close();  	
+			result1.text = "File loaded";	
+		}
+		else
+		{
+			ud = new UserDictionary();
+			result1.text = "File created";
+		}		
+		updateWordList();
+		sp.addUserDictionary(ud);
+	}
+	
+	public function saveDict():void
+	{
+		var outFile:File = File.desktopDirectory;
+		outFile = outFile.resolvePath(filename.text);
+		var outStream:FileStream = new FileStream();
+		outStream.open(outFile, FileMode.WRITE);
+		outStream.writeObject(ud.wordList);
+		outStream.close();
+		result1.text = "File saved"
+	}
+	
+	public function addWord():void
+	{
+		ud.addWord(word.text);
+		updateWordList();
+	}
+	
+	public function removeWord():void
+	{
+		ud.removeWord(word.text);
+		updateWordList();
+	}
+	
+	]]>
+</mx:Script>		
+	<mx:HBox>
+		<mx:TextInput id="filename" text="mywords.ud"/>
+		<mx:Button id="load" label="Load/New dictionary" click="loadDict()" />
+		<mx:Button id="save" label="Save dictionary" click="saveDict()" />
+		<mx:Label id="result1" text="Result:"/> 
+	</mx:HBox>	
+	<mx:HBox>
+		<mx:TextInput id="word" text="myword"/>
+		<mx:Button id="add" label="Add Word" click="addWord()" />
+		<mx:Button id="remove" label="Remove word" click="removeWord()" />
+		<mx:Label id="result2" text="Result:"/> 
+	</mx:HBox>
+	<mx:TextArea id="wordList" height="100" width="100"/>
+	
+	<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+	<mx:Button id="check" label="Check Word" click="checkWord()"  />
+	<mx:Label id ="result" text="Result:"/>
+</mx:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/CheckWord/src/CheckWord.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/CheckWord/src/CheckWord.mxml b/Squiggly/ane/Examples/Flex/CheckWord/src/CheckWord.mxml
new file mode 100644
index 0000000..d10b506
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/CheckWord/src/CheckWord.mxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" applicationComplete="init()">
+<mx:Script>
+	<![CDATA[
+		import com.adobe.linguistics.spelling.*;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+				_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+				_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkWord():void {
+			if( sp.checkWord( inputWord.text ) )
+				result.text = "Result:correct";
+			else
+				result.text = "Result:wrong";
+		}
+		
+	]]>
+</mx:Script>
+	<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+	<mx:Label id ="result" text="Result:"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/ConfigExample/src/ConfigExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/ConfigExample/src/ConfigExample.mxml b/Squiggly/ane/Examples/Flex/ConfigExample/src/ConfigExample.mxml
new file mode 100644
index 0000000..9d516d9
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/ConfigExample/src/ConfigExample.mxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html" applicationComplete="init()">		
+	<mx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;
+			import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+			import com.adobe.linguistics.spelling.framework.ResourceTable;
+			
+			
+			public function init():void
+			{
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});
+				resourceTable.setResource("es_ES", {rule:"data/es_ES.aff", dict:"data/es_ES.dic"});
+				SpellingConfiguration.resourceTable = resourceTable;
+			}
+			public function spellEnglish():void
+			{
+				SpellUI.enableSpelling(ta_en,"en_US");
+			}
+			public function spellSpanish():void
+			{
+				SpellUI.enableSpelling(ta_es,"es_ES");
+			}
+			
+		]]>
+	</mx:Script>
+	
+	<mx:Label text="ConfigExample.mxml Spell checks using SpellingConfiguration class. Does not need AdobeSpellingConfig.xml" fontSize="20"/>
+	
+	
+		
+		<mx:TextArea id="ta_en" width="50%" height="20%"
+						 text="I know Enlish. Use the context menu to see the suggestions of the missbelled word. " />
+		<mx:Button label="Spell English" id="b1" click="spellEnglish()"/>
+		
+		<mx:TextArea id="ta_es" width="50%" height="20%"
+						 text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita. " />
+		<mx:Button label="Spell Spanish" id="b2" click="spellSpanish()"/>
+
+</mx:Application>
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
new file mode 100644
index 0000000..e6d6928
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
@@ -0,0 +1,23 @@
+################################################################################
+##
+##  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.
+##
+################################################################################
+
+# locale/en_US/SquigglyContextMenu.properties
+add=Add to dictionary
+enable=Enable spelling
+disable=Disable spelling

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
new file mode 100644
index 0000000..e85b091
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
@@ -0,0 +1,23 @@
+################################################################################
+##
+##  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.
+##
+################################################################################
+
+# locale/es_ES/SquigglyContextMenu.properties
+add=Añadir al diccionario
+enable=Revisar ortografía
+disable=Ignorar ortografía

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
new file mode 100644
index 0000000..166255d
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="init();">
+	<mx:Script>
+		<![CDATA[
+
+			import com.adobe.linguistics.spelling.SpellUI;
+			
+			[Bindable]
+			private var uiLocales:Array = ["en_US", "es_ES" ];
+			
+			private function uiLocaleChange():void
+			{
+				resourceManager.localeChain = [ localeComboBox.selectedItem ];
+				updateContextMenuForLocaleChange();
+			}
+				
+			private function updateContextMenuForLocaleChange():void
+			{
+				var contextMenu:Object = 
+					{add:resourceManager.getString('SquigglyContextMenu', 'add'),
+					 enable:resourceManager.getString('SquigglyContextMenu', 'enable'),
+					 disable:resourceManager.getString('SquigglyContextMenu', 'disable')};
+				SpellUI.setSpellingMenuEntries(contextMenu);
+			}
+			
+			private function init():void
+			{
+				SpellUI.enableSpelling(ta, "en_US");
+			}
+		]]>
+    </mx:Script>
+    
+    <mx:Metadata>
+    	[ResourceBundle("SquigglyContextMenu")]
+    </mx:Metadata>
+	<mx:Label text="Example for contextMenu customization with resource" fontSize="30"/>
+	<mx:HBox>
+		<mx:Text text="Locale for Squiggly contextMenu" color="blue"/>	
+		<mx:ComboBox id="localeComboBox" dataProvider="{uiLocales}" change="uiLocaleChange()"/>
+	</mx:HBox>
+	<mx:TextArea id="ta" width="50%" height="50%" fontSize="30" y="50" text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita."/>
+</mx:Application>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml b/Squiggly/ane/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
new file mode 100644
index 0000000..854c450
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="init();">
+	<mx:Script>
+		<![CDATA[
+
+			import com.adobe.linguistics.spelling.SpellUI;
+				
+			public function init():void
+			{
+				// This is just for example code purpose, we recommend using this with resource bundle rather than using hard coded string.
+				var spanishEntries:Object = {enable:"Revisar ortografía", disable:"Ignorar ortografía", add:"Añadir al diccionario"};
+				var result:Boolean = SpellUI.setSpellingMenuEntries(spanishEntries);
+				if (result == false) trace("Error customizing contextMenu, default menu will be used");
+				
+				SpellUI.enableSpelling(ta, "en_US");
+			}	
+		]]>
+    </mx:Script>
+    
+	<mx:Label text="Example for Spanish contextMenu" fontSize="30"/>
+	<mx:TextArea id="ta" width="50%" height="50%" fontSize="30" y="50"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml b/Squiggly/ane/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
new file mode 100644
index 0000000..df0221f
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" horizontalAlign="left">
+<mx:Script>
+	<![CDATA[
+		import com.adobe.linguistics.spelling.*;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+				_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+				_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkWord():void {
+			suggestions.text= "";
+			if( sp.checkWord( inputWord.text ) ) {
+				result.text = "Result:correct";
+			}
+			else {
+				result.text = "Result:wrong";
+				var sugeestionArr:Array= sp.getSuggestions(inputWord.text);
+				if (sugeestionArr != null) {
+					for ( var i:int=0;i< sugeestionArr.length; i++ ) {
+						suggestions.text= suggestions.text + sugeestionArr[i] + "\n";
+					}
+				}
+			}
+		}
+		
+	]]>
+</mx:Script>
+	<mx:HBox>
+		<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+		<mx:Button id="check" label="Check Word" click="checkWord()"  />
+		<mx:Label id ="result" text="Result:"/>	
+	</mx:HBox>
+	<mx:TextArea id="suggestions" height="300" width="100"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml b/Squiggly/ane/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
new file mode 100644
index 0000000..b1afb2d
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+			   xmlns:s="library://ns.adobe.com/flex/spark" 
+			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="init();">
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.framework.*;
+			import com.adobe.linguistics.spelling.*;
+			
+			private var spellingService:SpellingService = null;
+			
+			private function init():void {
+				result.text += "AdobeSpellingServiceFramework tests\n===================\n";
+				result.text += "Setting SpellingConfiguration and initializing SpellingService ...\n";
+				
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});			
+				SpellingConfiguration.resourceTable = resourceTable;
+				
+				spellingService = new SpellingService("en_US");
+				spellingService.addEventListener(Event.COMPLETE, spellingServiceReady);
+				spellingService.init();
+			}
+			
+			private function spellingServiceReady(e:Event):void {
+				result.text += "SpellingService ready for use\n";
+				
+				result.text += "Checking \"hello\" ... " + spellingService.checkWord("hello") + "\n";
+				result.text += "Checking \"heello\" ... " + spellingService.checkWord("heello") + "\n";
+				result.text += "Getting suggestions for \"heello\" ... " + spellingService.getSuggestions("heello") + "\n";
+				
+				
+				var ud:UserDictionary = new UserDictionary();
+				result.text += "Adding \"heello\" to UserDictionary ..." + ud.addWord("heello") + "\n";
+				result.text += "Adding UserDicitonary to SpellingService ..." + spellingService.addUserDictionary(ud) +"\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Removing \"heello\" from UserDictionary ..." + ud.removeWord("heello") + "\n"
+				result.text += "Checking \"heello\" again, expect false ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Number of UserDictionary, expect 1 ..." + spellingService.userDictionaries.length + "\n";
+				
+				var ud2:UserDictionary = new UserDictionary();				
+				result.text += "Adding UserDicitonary 2 to SpellingService ..." + spellingService.addUserDictionary(ud2) +"\n";
+				result.text += "Adding \"heello\" to UserDictionary 2 ..." + ud2.addWord("heello") + "\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 2 ..." + spellingService.userDictionaries.length + "\n";
+				
+				spellingService.removeUserDictionary(ud);
+				spellingService.removeUserDictionary(ud2);
+				result.text += "Checking \"heello\" again after removing all UserDictionaries, expect false ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 0 ..." + spellingService.userDictionaries.length + "\n";
+				
+			}
+			
+		]]>
+	</fx:Script>
+	<mx:Text id="result"/>
+</s:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml b/Squiggly/ane/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
new file mode 100644
index 0000000..086a591
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">		
+<mx:Script>
+	<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;	
+			
+			private function enableFeature():void {
+				SpellUI.enableSpelling(textArea, "en_US");
+			}
+			private function disableFeature() :void {
+				SpellUI.disableSpelling(textArea);
+			
+			}
+	]]>
+</mx:Script>
+		
+	<mx:TextArea id="textArea" width="20%" height="20%" fontSize="30" text="Spell cheecking in TextArea "/>
+	<mx:Button id="tt1" label="disable Feature" click="disableFeature()" /> 
+	<mx:Button id="tt2" label="enable Feature" click="enableFeature()" /> 
+			
+</mx:Application>
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/Flex/TextEditor/src/TextEditor.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/Flex/TextEditor/src/TextEditor.mxml b/Squiggly/ane/Examples/Flex/TextEditor/src/TextEditor.mxml
new file mode 100644
index 0000000..b86191d
--- /dev/null
+++ b/Squiggly/ane/Examples/Flex/TextEditor/src/TextEditor.mxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" horizontalAlign="left">
+<mx:Script>
+	<![CDATA[
+
+		import com.adobe.linguistics.spelling.*;
+		import mx.controls.textClasses.TextRange;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+			_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+			_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkText():void {
+			var wordPattern:RegExp =/\b\w+\b/; // match next word...
+			var inputValue:String = inputText.text;
+			var offset:int, curPos:int;
+			for ( ; ; ) {
+				var res:Array = inputValue.match( wordPattern); // lookup word by word....
+				if ( res == null ) break;
+				if ( !sp.checkWord(res[0]) ) {
+					offset = inputText.text.length-inputValue.length;
+					curPos = inputValue.indexOf(res[0]);
+					var currentRange:TextRange = new TextRange(inputText, false, offset+ curPos, offset+ curPos+res[0].length); // mark mispelled word.
+					currentRange.color = "red";
+				}
+				inputValue = inputValue.substr(inputValue.indexOf(res[0])+ res[0].length);
+			}
+		}
+		
+	]]>
+</mx:Script>
+	<mx:HBox>
+		<mx:Button id="check" label="Check Text" click="checkText()"  />
+	</mx:HBox>
+	<mx:TextArea id="inputText" height="100%" width="100%"/>	
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Examples/HowToUseExamples.txt
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Examples/HowToUseExamples.txt b/Squiggly/ane/Examples/HowToUseExamples.txt
new file mode 100644
index 0000000..80670d8
--- /dev/null
+++ b/Squiggly/ane/Examples/HowToUseExamples.txt
@@ -0,0 +1,34 @@
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+How to use Squiggly examples
+===================================
+
+To build and run an example, please follow these steps:
+
+1. Import the project into Flex Builder 3 or Flash Builder 4 beta.
+
+2. Copy the dictionary data (including the AdobeSpellingConfig.xml file and the dictionaries folder) from ../src to <project>/src folder. If you want to place the dictionary files in a different folder, please make sure the url is referred correctly in the code or in AdobeSpellingConfig.xml file.
+
+3. Copy the Squiggly lib(s) from ../libs to <project>/libs folder
+   - CheckWord, GetSuggestion, TextEditor needs only AdobeSpellingEngine.swc
+   - SquigglyUIExample, ContextMenuWithResource, CustomContextMenu needs both AdobeSpellingEngine.swc and AdobeSpellingUI.swc
+   - SquigglyTLFExample needs AdobeSpellingUIForTLF.swc
+
+4. Build the project
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.cpp b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.cpp
new file mode 100644
index 0000000..3d456c6
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.cpp
@@ -0,0 +1,294 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.cpp
+
+	Author: Sudhakar Pandey <su...@adobe.com>
+*/
+
+
+#include <iostream>
+#include <cstring>
+#include <stdexcept>
+#include "EncConv.h"
+
+extern "C" 
+{
+    #include "unicode/ucnv.h"   //Adding this as an alternative to native iconv library
+    #include "unicode/ustring.h"   //Adding this as an alternative to native iconv library
+}
+#ifndef MAX
+		#define	MAX(a,b) (((a)>(b))?(a):(b))
+	#endif /* MAX */
+// =============================================================================
+
+namespace EncConv
+{
+
+// -----------------------------------------------------------------------------
+
+U16Char_t* convSpecialCharsInU16Str(const U16Char_t* src)
+{
+	const LM_UInt32 srcLen = GetNumOfUnits(src);
+	U16Char_t* pdst = new U16Char_t [srcLen + 1];
+	 
+	LM_UInt32 i;
+	for(i = 0; i < srcLen; ++i)
+	{
+		U16Char_t c = src[i];
+		switch (c)
+		{
+		case 0x2018:		// U+2018: Left Single Quotation Mark
+		case 0x2019:		// U+2019: Right Single Quotation Mark
+					c = '\'';	break;
+		case 0x201C:		// U+201C: Left Double Quotation Mark
+		case 0x201D:		// U+201D: Right Double Quotation Mark
+					c = '"';	break;
+		}
+		pdst[i] = c;
+	}
+	pdst[i] = 0;
+	return pdst;
+	//delete[] pdst;
+	//should be deleted by calling releaseU16CharString() function.
+}
+
+const char * getPlatformEncoding(const char* enc)
+{
+	//If encoding is null or not specified then try the default encoding "ISO-8859-1"
+	if(strlen(enc) == 0)
+		return "ISO-8859-1";
+	if(strcmp(enc,"ISO8859-1") == 0)
+		return "ISO-8859-1";
+	else if (strcmp(enc,"ISO8859-2") == 0)
+		return "ISO-8859-2";
+	else if (strcmp(enc,"ISO8859-3") == 0)
+		return "ISO-8859-3";
+	else if (strcmp(enc,"ISO8859-4") == 0)
+		return "ISO-8859-4";
+	else if (strcmp(enc,"ISO8859-5") == 0)
+		return "ISO-8859-5";
+	else if (strcmp(enc,"ISO8859-6") == 0)
+		return "ISO-8859-6";
+	else if (strcmp(enc,"ISO8859-7") == 0)
+		return "ISO-8859-7";
+	else if (strcmp(enc,"ISO8859-8") == 0)
+		return "ISO-8859-8";
+	else if (strcmp(enc,"ISO8859-9") == 0)
+		return "ISO-8859-9";
+	else if (strcmp(enc,"ISO8859-10") == 0)
+		return "ISO-8859-10";
+	else if (strcmp(enc,"KOI8-R") == 0)
+		return "KOI8-R";
+	else if (strcmp(enc,"KOI8-U") == 0)
+		return "KOI8-U";
+	else if (strcmp(enc,"microsoft-cp1251") == 0)
+		return "cp1251";
+	else if (strcmp(enc,"ISO8859-13") == 0)
+		return "ISO-8859-13";
+	else if (strcmp(enc,"ISO8859-14") == 0)
+		return "ISO-8859-14";
+	else if (strcmp(enc,"ISO8859-15") == 0)
+		return "ISO-8859-15";
+	else if (strcmp(enc,"ISCII-DEVANAGARI") == 0)
+		return "ibm-1137";
+	else if (strcmp(enc,"TIS620-2533") == 0)
+		return "TIS-620";
+	else if (strcmp(enc,"UTF-8") == 0)
+		return "UTF-8";
+	else
+		return enc;
+}
+
+
+const std::string convU16StrToCharStr(const U16Char_t* src, const char* Encoding)
+{
+	//static char const* const tocode = CHARCONV_ICONV_UTF16;
+	char const* const tocode = getPlatformEncoding(Encoding);
+    
+    UErrorCode status = U_ZERO_ERROR;
+
+#ifdef ENCCONV_DEBUG
+	std::cout << "\t" "convString" << std::endl;
+	std::cout << "\t\t" "tocode   = " << tocode   << std::endl;
+	//std::cout << "\t\t" "fromcode = " << fromcode << std::endl;
+#endif
+
+	//iconv_t cd = iconv_open(tocode, fromcode);
+    // Initializing ICU converter
+	UConverter *conv = ucnv_open(tocode, &status);
+
+#ifdef CHARCONV_DEBUG
+	std::cout << "\t\t" "aft ucnv_open: status = " << status << std::endl;
+#endif
+	if (conv == NULL)
+	{ // try default encoding "ISO-8859-1"
+		//throw std::runtime_error("Unable to create Unicode converter object");
+		status = U_ZERO_ERROR;
+		conv = ucnv_open("ISO-8859-1", &status);
+	}
+
+	//still if conv is null simply return blank string
+
+	if (conv == NULL)
+	{ 
+		return std::string("");
+	}
+
+	U16Char_t const* srcWrk = src;
+	const size_t srcSizeInUnits = GetNumOfUnits(src);
+	const size_t srcSizeInBytes = srcSizeInUnits * sizeof(U16Char_t);
+	const size_t dstSizeInBytes = MAX(256, (srcSizeInUnits + 1)) * 4;	// How much byte buffer is needed? (UTF16 --> MBCS)
+	char* dst = new char [dstSizeInBytes];
+	if(dst==NULL) 
+	{
+		//Fix for #3211945
+		ucnv_close(conv);
+		return std::string("");
+	}
+	char* dstWrk =(char*)(dst);
+	size_t srcLeftInBytes = srcSizeInBytes;
+	size_t dstLeftInBytes = dstSizeInBytes - sizeof(char);
+    status = U_ZERO_ERROR;
+
+		ucnv_fromUChars(conv, dstWrk, dstLeftInBytes, (UChar*)srcWrk, -1, &status);
+		U16Char_t* reverseConvertedVal = convCharStrToU16Str(dstWrk,Encoding);
+		if(strcmp((char*)reverseConvertedVal,(char*)src)!=0)
+		{
+			EncConv::releaseU16Str(reverseConvertedVal);
+			//Fix for #3211945
+			dstWrk = NULL;
+			ucnv_close(conv);
+	        delete[] dst;
+			
+			return std::string("");
+		}
+		EncConv::releaseU16Str(reverseConvertedVal);
+		
+	
+#ifdef CHARCONV_DEBUG
+		std::cout << "\t\t" "aft iconv: status = " << status << std::endl;
+#endif
+		if (status != U_ZERO_ERROR )
+		{
+			//	throw std::runtime_error("Unable to convert to string");
+			*dstWrk = 0;
+		}
+
+
+		std::string dst2(dst);
+		//Fix for #3211945 
+		dstWrk = NULL;
+        delete[] dst;
+	//const int err = iconv_close(cd);
+
+    ucnv_close(conv);
+
+	//if (err == -1)
+	//	throw std::runtime_error("Unable to deallocate iconv_t object");
+
+        return dst2;
+}
+
+U16Char_t* convCharStrToU16Str(const char* src, const char* Encoding)
+{
+
+	//static char const* const tocode = CHARCONV_ICONV_UTF16;
+	char const* const fromcode = getPlatformEncoding(Encoding);
+    
+    UErrorCode status = U_ZERO_ERROR;
+
+#ifdef ENCCONV_DEBUG
+	std::cout << "\t" "convString" << std::endl;
+	//std::cout << "\t\t" "tocode   = " << tocode   << std::endl;
+	std::cout << "\t\t" "fromcode = " << fromcode << std::endl;
+#endif
+
+	//iconv_t cd = iconv_open(tocode, fromcode);
+    // Initializing ICU converter
+    UConverter *conv= ucnv_open(fromcode, &status);
+#ifdef CHARCONV_DEBUG
+	std::cout << "\t\t" "aft ucnv_open: status = " << status << std::endl;
+#endif
+	if (conv == NULL)
+	{ // try default encoding "ISO-8859-1"
+		//throw std::runtime_error("Unable to create Unicode converter object");
+		conv = ucnv_open("ISO-8859-1", &status);
+	}
+
+	
+
+	char const* srcWrk = src;
+	const size_t srcSizeInBytes = std::strlen(src);
+	const size_t dstSizeInBytes = MAX(256, (srcSizeInBytes + 1)) * sizeof(U16Char_t);
+	U16Char_t* dst = new U16Char_t [dstSizeInBytes / sizeof(U16Char_t)];
+	U16Char_t* dstWrk = dst;
+	size_t srcLeftInBytes = srcSizeInBytes;
+	size_t dstLeftInBytes = dstSizeInBytes - sizeof(U16Char_t);
+
+    status = U_ZERO_ERROR;
+
+	//still if conv is null simply return blank string
+
+	if (conv == NULL)
+	{ 
+		dst[0] = NULL;
+		//Fix for #3211945
+		dstWrk = NULL;
+		return dst;
+	}
+
+	ucnv_toUChars(conv, (UChar *) dstWrk, dstLeftInBytes, (char*)srcWrk, srcLeftInBytes, &status);
+	
+#ifdef CHARCONV_DEBUG
+		std::cout << "\t\t" "aft iconv: status = " << status << std::endl;
+#endif
+		if (status != U_ZERO_ERROR )
+		{
+			//	throw std::runtime_error("Unable to convert to string");
+			*dstWrk = 0;
+		}
+
+
+	//const int err = iconv_close(cd);
+
+    ucnv_close(conv);
+
+	//if (err == -1)
+	//	throw std::runtime_error("Unable to deallocate iconv_t object");
+	//Fix for #3211945
+	dstWrk = NULL;
+	return dst;
+
+}
+
+void releaseU16Str(const U16Char_t* buf)
+{
+		if(buf != NULL)
+		{
+			delete[] buf;
+			buf = NULL;
+		}
+		return;
+}
+
+}// namespace
+// -----------------------------------------------------------------------------
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.h b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.h
new file mode 100644
index 0000000..22ee0c9
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/EncConv.h
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.h
+
+	Author: Sudhakar Pandey <su...@adobe.com>
+*/
+
+#ifndef __ENCCONV_H__
+#define __ENCCONV_H__
+
+
+#include <string>
+extern "C"
+{
+    #include "unicode/ucnv.h"
+}
+typedef unsigned short U16Char_t;
+typedef unsigned long	LM_UInt32;
+
+namespace EncConv
+{
+	template<class CharType>
+	static size_t GetNumOfUnits(CharType const* src)
+	{
+		size_t numOfUnits = 0;
+		while (*src++ != 0)
+			++numOfUnits;
+
+		return numOfUnits;
+	}
+
+	const char * getPlatformEncoding(char* enc);
+	const std::string convU16StrToCharStr(const U16Char_t* src, const char* Encoding);
+	U16Char_t* convCharStrToU16Str(const char* src, const char* Encoding);
+
+	U16Char_t* convSpecialCharsInU16Str( const U16Char_t* src); // caller need not allocate memory for the return value U16Char_t* 
+	void releaseU16Str(const U16Char_t* buf);
+
+}	// namespace
+
+#endif

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/English.lproj/InfoPlist.strings
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/English.lproj/InfoPlist.strings b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..88f65cf
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/English.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Exported_Sym_FIle
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Exported_Sym_FIle b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Exported_Sym_FIle
new file mode 100644
index 0000000..1bd943b
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Exported_Sym_FIle
@@ -0,0 +1,4 @@
+_ContextFinalizer
+_ContextInitializer
+_ExtFinalizer
+_ExtInitializer

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
new file mode 100644
index 0000000..29eddce
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
@@ -0,0 +1,368 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <string>
+#include <Adobe AIR/Adobe AIR.h>
+
+#include "hunspell.hxx"
+#include "HunspellNativeExtension.h"
+#include "EncConv.h"
+#include "Utilities.h"
+#define HUNSPELL_INIT_SUCCESS 1
+
+using namespace EncConv;
+
+
+// Symbols tagged with EXPORT are externally visible.
+// Must use the -fvisibility=hidden gcc option.
+#define EXPORT __attribute__((visibility("default")))
+
+void* hinstLib;
+typedef Hunspell * (*HUNSPELL_INIT)(char *, char*);
+typedef int (*HUNSPELL_SPELL)(Hunspell *, char *);
+typedef int (*HUNSPELL_SUGGEST)(Hunspell *, char ***, char *);
+typedef void (*HUNSPELL_FREE_LIST)(Hunspell *, char ***, int);
+typedef char *(*HUNSPELL_GET_ENCODING)(Hunspell *);
+typedef void (*HUNSPELL_UNINIT)(Hunspell *);
+
+extern "C"
+{
+	
+    Hunspell * getHunspellObject(std::string locale)
+    {
+        Hunspell_cache_iterator iter;
+        if((iter=Hunspell_cache.find(locale)) == Hunspell_cache.end() )
+            return NULL;
+        else
+            return iter->second;
+    }
+
+    
+    FREObject talkBack(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+       // const uint8_t *locale = 0;
+        const uint8_t *inpWord = 0;
+        uint32_t len = 0;
+        FREObject retObj=0;
+        
+        //get first argument
+        if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+            return retObj;
+        
+        FRENewObjectFromUTF8((uint32_t)(strlen((char *)inpWord)),(const uint8_t*)(inpWord), &retObj);
+        
+        return retObj;
+        
+    }
+    
+    
+    FREObject initHunspellObject(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){
+        const uint8_t *locale = 0;
+        const uint8_t *dictionaryPath = 0;
+        uint32_t len = -1;
+        FREObject retObj=0;
+       
+        Hunspell * hunspellObject;
+        //get first argument
+        if(FREGetObjectAsUTF8(argv[1], &len, &dictionaryPath) != FRE_OK)
+            return retObj;
+        len = 0;
+        
+        //get second argument
+        if(FREGetObjectAsUTF8(argv[0], &len, &locale) != FRE_OK)
+            return retObj;
+        
+        //check in cache and return if already present
+        if(!(Hunspell_cache.find(std::string((char *)locale))==Hunspell_cache.end()))
+		{
+			FRENewObjectFromInt32(HUNSPELL_INIT_SUCCESS, &retObj);
+			return retObj;
+		}
+        
+       // U16Char_t * dic_path_U16= EncConv::convCharStrToU16Str((char *)dictionaryPath, "UTF-8");
+       // U16Char_t *locale_U16= EncConv::convCharStrToU16Str((char *)locale, "UTF-8");
+  
+       // std::wstring aff_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"/Dictionaries/")+std::wstring((wchar_t *)locale_U16)+std::wstring(L"/")+std::wstring((wchar_t *)locale_U16)+std::wstring(L".aff");
+       // std::wstring dic_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"/Dictionaries/")+std::wstring((wchar_t *)locale_U16)+std::wstring(L"/")+std::wstring((wchar_t *)locale_U16)+std::wstring(L".dic");
+       // std::wstring lib_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"/libhunspell.dylib");
+     
+        
+        
+        //creating OS specific aff,dic file paths refer: DanishOS Issue of CS6 AHP 
+   //     std::string aff_file_U8= makeString(aff_file.c_str());
+   //     std::string dic_file_U8= makeString(dic_file.c_str());
+        
+        //make the file url's
+        std::string lib_file_U8= std::string((char *)dictionaryPath)+std::string("/libhunspell.dylib");
+        std::string aff_file_U8= std::string((char *)dictionaryPath)+std::string("/Dictionaries/")+std::string((char *)locale)+std::string("/")+std::string((char *)locale)+std::string(".aff");
+        std::string dic_file_U8= std::string((char *)dictionaryPath)+std::string("/Dictionaries/")+std::string((char *)locale)+std::string("/")+std::string((char *)locale)+std::string(".dic");
+        
+      
+    //    fprintf(stderr,"Path, %s", lib_file_U8.c_str());
+    //    fprintf(stderr,"Path, %s", aff_file_U8.c_str());
+    //    fprintf(stderr,"Path, %s", lib_file_U8.c_str());
+        
+        
+        //check for file is present
+        
+        if( (FileExists(aff_file_U8.c_str()) && FileExists(dic_file_U8.c_str()) && FileExists(lib_file_U8.c_str())) == false )
+        {
+            FRENewObjectFromInt32(RESOURCE_FILES_MISSING, &retObj);
+            return retObj;
+        }
+        
+        //make a new hunspell object
+    //    hinstLib = dlopen("/Users/ugoyal/Desktop/ThirdPartyResources/libhunspell.dylib", RTLD_LAZY); 
+        hinstLib = dlopen(lib_file_U8.c_str(), RTLD_LAZY); 
+        
+        if (hinstLib != NULL) 
+        { 
+            HUNSPELL_INIT initAdd = (HUNSPELL_INIT) dlsym(hinstLib, "Hunspell_create"); 
+            
+            // If the function address is valid, call the function.
+            
+            if (NULL != initAdd) 
+            {
+                hunspellObject = (initAdd) ((char *)aff_file_U8.c_str(), (char *)dic_file_U8.c_str());
+              // hunspellObject = (*initAdd)("/Users/ugoyal/Desktop/ThirdPartyResources/Dictionaries/de_DE/de_DE.aff","/Users/ugoyal/Desktop/ThirdPartyResources/Dictionaries/de_DE/de_DE.dic");
+            }
+            
+        } 
+        
+        //add to hunspell cache	
+        if(Hunspell_cache.find(std::string((char *)locale))==Hunspell_cache.end())	
+            Hunspell_cache[std::string((char *)locale)]= hunspellObject;
+        
+     
+        if(hunspellObject)
+        {
+            FRENewObjectFromInt32(HUNSPELL_INIT_SUCCESS, &retObj);
+        }
+        else
+        {
+            FRENewObjectFromInt32(HUNSPELL_INIT_FAIL, &retObj);
+        }
+        
+        return retObj;
+    }
+    
+    FREObject checkWord(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+        const uint8_t *locale = 0;
+        const uint8_t *inpWord = 0;
+        uint32_t len = -1;
+        FREObject retObj=0;
+        int rv=0;
+        
+        U16Char_t* inpWordU16 = NULL;
+        std::string  inpWordDictEncoded;
+        bool isConversionUnSuccesful=false;
+        //get first argument
+        if(FREGetObjectAsUTF8(argv[1], &len, &locale) != FRE_OK)
+            return retObj;
+        len = 0;
+        
+        //get second argument
+        if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+            return retObj;
+        
+        //get the hunspell object from cache
+        Hunspell * hunspellObject=getHunspellObject(std::string((char *)locale));
+		
+        if(!hunspellObject) 
+            return retObj;
+		
+        
+        //convert input utf8 to u16 string
+         inpWordU16 = EncConv::convCharStrToU16Str((char *)inpWord, "UTF-8");
+        
+        //get dictionary encoding
+       HUNSPELL_GET_ENCODING getEncAdd=(HUNSPELL_GET_ENCODING) dlsym(hinstLib, "Hunspell_get_dic_encoding");
+        char * m_MainEncoding= (*getEncAdd)(hunspellObject);
+        
+        //convert u16 to dictionary encoding
+        inpWordDictEncoded=EncConv::convU16StrToCharStr(inpWordU16,m_MainEncoding);
+        
+        if(inpWordDictEncoded.length()==0)
+        {
+            isConversionUnSuccesful = true;
+        }
+        
+        //Get spellAddress
+        HUNSPELL_SPELL spellAdd= (HUNSPELL_SPELL) dlsym(hinstLib, "Hunspell_spell");
+        
+        //Do spell check with converted word else try with UTF-8
+        if((!isConversionUnSuccesful) )
+        {
+            rv= (*spellAdd)(hunspellObject, (char * )inpWordDictEncoded.c_str());
+           
+        }
+        else
+        { 
+            rv= (*spellAdd)(hunspellObject, (char * )inpWord);
+        }
+		
+        //return results
+        EncConv::releaseU16Str(inpWordU16);
+        FRENewObjectFromInt32(rv, &retObj);
+        return retObj;
+    }
+    
+    FREObject getSuggestions(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+        const uint8_t *locale = 0;
+        const uint8_t *inpWord = 0;
+        uint32_t len = -1;
+        FREObject retObj=0;
+        FREObject oneSuggestion=0;
+        
+        U16Char_t* inpWordU16 = NULL;
+        std::string  inpWordDictEncoded;
+        bool isConversionUnSuccesful=false;
+        char * oneSuggestionEncoded=NULL;
+        U16Char_t * oneSuggestionU16=NULL;
+        std::string oneSuggestionU8;
+        
+        //assign memory to retobj
+        FRENewObject((const uint8_t*)"Array", 0, NULL, &retObj, 0);
+        
+        //get first argument
+        if(FREGetObjectAsUTF8(argv[1], &len, &locale) != FRE_OK)
+            return retObj;
+        len = 0;
+        
+        //get second argument
+        if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+            return retObj;
+        
+        //get the hunspell object from cache
+        Hunspell * hunspellObject=getHunspellObject(std::string((char *)locale));
+		
+        if(!hunspellObject) return retObj;
+        
+        //convert input utf8 to u16 string
+        inpWordU16 = EncConv::convCharStrToU16Str((char *)inpWord, "UTF-8");
+        
+        //get dictionary encoding
+    HUNSPELL_GET_ENCODING getEncAdd=(HUNSPELL_GET_ENCODING) dlsym(hinstLib, "Hunspell_get_dic_encoding");
+        char * m_MainEncoding= (getEncAdd)(hunspellObject);
+        
+        //convert u16 to dictionary encoding
+        inpWordDictEncoded=EncConv::convU16StrToCharStr(inpWordU16,m_MainEncoding);
+        
+        if(inpWordDictEncoded.length()==0)
+        {
+            isConversionUnSuccesful = true;
+        }
+        
+        //get suggestAddress &freelistAddress
+        HUNSPELL_SUGGEST suggestAdd= (HUNSPELL_SUGGEST) dlsym(hinstLib, "Hunspell_suggest");
+        HUNSPELL_FREE_LIST freeListAdd= (HUNSPELL_FREE_LIST) dlsym(hinstLib, "Hunspell_free_list");
+        
+        char** suggList = NULL;
+        int numSugg = 0;
+        
+        //Try getting suggestions with encoded word else try with UTF8
+        if(suggestAdd && !isConversionUnSuccesful)
+        {
+            numSugg = (suggestAdd)(hunspellObject,&suggList,(char *) (inpWordDictEncoded.c_str()));
+        }
+        else
+        {
+            numSugg = (suggestAdd)(hunspellObject,&suggList ,(char *) (inpWord));
+        }
+        
+        
+        if(numSugg)
+        {
+            FRESetArrayLength( retObj, numSugg );
+            
+            for(int iCount=0; iCount <numSugg; iCount++)
+            {
+                oneSuggestionEncoded=suggList[iCount];
+                oneSuggestionU16=EncConv::convCharStrToU16Str(oneSuggestionEncoded, m_MainEncoding);
+                oneSuggestionU8= EncConv::convU16StrToCharStr(oneSuggestionU16, "UTF-8");
+                FRENewObjectFromUTF8((uint32_t)(oneSuggestionU8.length()),(const uint8_t*)(oneSuggestionU8.c_str()), &oneSuggestion);
+                FRESetArrayElementAt(retObj, iCount, oneSuggestion);
+                EncConv::releaseU16Str(oneSuggestionU16);
+            }
+            (freeListAdd)(hunspellObject, &suggList,numSugg);
+            
+        }
+        
+        EncConv::releaseU16Str(inpWordU16);
+        
+        return retObj;
+    }
+
+    
+    
+	void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, 
+		uint32_t* numFunctionsToSet, const FRENamedFunction** functionsToSet)
+	{
+        *numFunctionsToSet = 4;
+        FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*5);
+        
+        func[0].name = (const uint8_t*)"talkBack";
+        func[0].functionData = NULL;
+        func[0].function = &talkBack;
+        
+        func[1].name = (const uint8_t*)"initHunspellObject";
+        func[1].functionData = NULL;
+        func[1].function = &initHunspellObject;
+        
+        func[2].name = (const uint8_t*)"checkWord";
+        func[2].functionData = NULL;
+        func[2].function = &checkWord;
+        
+        func[3].name = (const uint8_t*)"getSuggestions";
+        func[3].functionData = NULL;
+        func[3].function = &getSuggestions;
+        
+        *functionsToSet = func;
+	}
+
+	void ContextFinalizer(FREContext ctx)
+	{
+	}
+
+	// Framework entry point
+	EXPORT
+	void ExtInitializer(void** extDataToSet, 
+		FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet)
+	{
+        *extDataToSet = NULL;
+		*ctxInitializerToSet = ContextInitializer;
+		*ctxFinalizerToSet = ContextFinalizer;
+	}
+
+	// Framework entry point
+	EXPORT
+	void ExtFinalizer(void* extData)
+	{
+        HUNSPELL_UNINIT uninitAdd= (HUNSPELL_UNINIT) dlsym(hinstLib, "Hunspell_destroy");
+        //clear all hunspell cache
+        for(Hunspell_cache_iterator hunspell_cache_iter= Hunspell_cache.begin(); hunspell_cache_iter != Hunspell_cache.end(); hunspell_cache_iter++)
+        {
+            (uninitAdd)(hunspell_cache_iter->second);
+            hunspell_cache_iter->second=NULL;
+        }
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
new file mode 100644
index 0000000..4591cc9
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef HunspellNativeExtension_HunspellNativeExtension_h
+#define HunspellNativeExtension_HunspellNativeExtension_h
+
+#include<map>
+#define HUNSPELL_INIT_FAIL -1
+#define RESOURCE_FILES_MISSING -2
+
+#define HUNSPELL_INIT_SUCCESS 1
+
+
+typedef std::map< std::string, Hunspell * > Hunspell_cache_type;
+typedef std::map< std::string, Hunspell * >::iterator Hunspell_cache_iterator;
+
+static Hunspell_cache_type Hunspell_cache;
+
+//Hunspell * getHunspellObject(std::string locale);
+
+#endif


[07/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/LinguisticRuleLoader.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/LinguisticRuleLoader.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/LinguisticRuleLoader.as
new file mode 100644
index 0000000..1b5bac9
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/LinguisticRuleLoader.as
@@ -0,0 +1,977 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	import com.adobe.linguistics.spelling.core.LinguisticRule;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.error.*;
+	import com.adobe.linguistics.spelling.core.logging.*;
+	
+	import flash.errors.IllegalOperationError;
+	import flash.events.ErrorEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IOErrorEvent;
+	import flash.events.SecurityErrorEvent;
+	import flash.net.URLRequest;
+	import flash.utils.ByteArray;
+
+	public class LinguisticRuleLoader extends EventDispatcher
+	{
+		private var _attrMgr:LinguisticRule;
+		private var _rulePath:String;
+		private var snp:SimpleNumberParser = new SimpleNumberParser();
+		
+		private var unrecognizedLines:int = 0;
+
+		
+		//setup logger for sending message.
+		private var className:String = flash.utils.getQualifiedClassName(this).split("::").join(".");
+		private var logger:ILogger = Log.getLogger( className );
+
+		public function LinguisticRuleLoader()
+		{
+			init();
+		}
+		
+		private function init():void {
+			_attrMgr = null;
+			_rulePath = null ;
+			unrecognizedLines = 0;
+			
+		}
+
+		public function load(ruleURL:String):void {
+			if ( ruleURL == null) {
+				throw new IllegalOperationError("Linguistics rule load function received an invalid URL.");
+			}
+			if ( this._attrMgr ) {
+				logger.warn("You already did call the load function muliti-times, The orginal linguistic data will be overiden." );
+				init();
+			}
+			_rulePath = ruleURL;
+			var request:URLRequest = new URLRequest( _rulePath );
+			var dloader:DictionaryLoader = new DictionaryLoader(request);
+			dloader.addEventListener(Event.COMPLETE,loadRuleComplete);
+			dloader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+			dloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+		}
+		//Private method to dispatch an error event.
+		private function handleError(evt:Event):void {
+			bounceEvent(evt);
+		}
+		private function bounceEvent(evt:Event):void {
+			dispatchEvent(evt.clone());
+		}
+
+		public function get linguisticRule():LinguisticRule {
+			return _attrMgr;
+		}
+
+		private function loadRuleComplete(evt:Event):void {
+			_attrMgr = new LinguisticRule();
+			if( !_attrMgr ) {
+				logger.fatal("Rule File[{0}] Operation[parsing]:Could not locate memory for Linguistic Rule", this._rulePath  );
+				return;
+			}
+			var bytes:ByteArray = evt.target.data;
+			detectEncoding(bytes);
+			bytes.position = 0;
+			parseRule(bytes);
+			dispatchEvent(new Event(Event.COMPLETE));
+		}
+		
+		private function parseRule(bytes:ByteArray):void {
+			
+			var str:String = 	bytes.readMultiByte(bytes.length, _attrMgr.encoding);
+			/*
+			In DOS, a line break is a single '\n'.
+			In Unix, a line break is the sequence '\r\n'.
+			In MAC, a line break is a single '\r'.
+			Correct me if I'm wrong.
+			so step 1:
+			replace "\r\n" with "\n"
+			step 2:
+			replace "\r" with "\n";
+			finally ,we get "\n" line seperator.
+			*/
+			str=str.split("\r\n").join("\n");
+			str=str.split("\r").join("\n");
+			var lineContentArr:Array = str.split("\n");
+			
+			//bof of parsing the text.
+			if( (lineContentArr== null) || (lineContentArr.length== 1) ) {
+				logger.fatal("Rule File[{0}] Operation[parsing] has nothing in the file.", this._rulePath  );
+				return;
+			}
+			/* remove byte order mark */
+			if ( lineContentArr[0].match(new RegExp("^\xEF\xBB\xBF[.]+$") ) ) lineContentArr[0]=lineContentArr[0].substr(3);
+
+			var lineContent:String;
+			var res:int;
+			for( var line:int = 0; line<lineContentArr.length; ) {
+				lineContent= lineContentArr[line];
+				
+				
+				if ( parseAttribute( lineContent, line ) ) {
+					++line;
+					continue;
+				}
+				//parsing for AF rule make aliasf table before loading alias rules
+				if( (res=parseAliasf(lineContent, lineContentArr, line) ) !=0){
+					++line;
+					line+=res;
+					continue;
+				}
+					
+				if ( (res=parseAffix(lineContent, lineContentArr, line)) != 0 ) {
+					line++;
+					line += res;
+					continue;
+				}
+				
+				
+				if ( (res=parseReplaceTable(lineContent, lineContentArr,line)) !=0 ) {
+					line++;
+					line += res;
+					continue;
+				}
+				if ( (res=parseMapTable(lineContent, lineContentArr, line) ) != 0 ) {
+					line++;
+					line += res;
+					continue;
+				}
+/*				//Parse phone table
+				if ( (res=parsePhoneTable(lineContent, lineContentArr,line)) !=0 ) {
+					line++;
+					line += res;
+					continue;
+				}
+*/				/*parse for ICONV/OCONV field*/
+				if ((res=parseConvTable(lineContent, lineContentArr,line)) !=0 ) {
+					line++;
+					line+=res;
+					continue;
+				}
+				
+				/*parse for BREAK rule*/
+				if ((res=parseBreakTable(lineContent, lineContentArr,line)) !=0 ) {
+					line++;
+					line+=res;
+					continue;
+				}
+				
+				if ( !isCommentOrEmpty( lineContent ) ) {
+					line++;
+					unrecognizedLines++;
+					logger.warn("Rule File[{0}] Operation[parsing] Line Number:{1}, Content:{2}",this._rulePath , (line+1).toString(),lineContent );
+					continue;
+				}
+				line++;
+			}
+			//eof of parsing the text.
+			logger.info("Rule File[{0}] Operation[parsing] Total Lines:{1}, Unrecognized Lines:{2}", this._rulePath ,lineContentArr.length.toString(), unrecognizedLines.toString() );
+			
+		}
+
+		private function detectEncoding(bytes:ByteArray):void {
+			var str:String = 	bytes.readUTFBytes(bytes.length);
+			/*
+			In DOS, a line break is a single '\n'.
+			In Unix, a line break is the sequence '\r\n'.
+			In MAC, a line break is a single '\r'.
+			Correct me if I'm wrong.
+			so step 1:
+			replace "\r\n" with "\n"
+			step 2:
+			replace "\r" with "\n";
+			finally ,we get "\n" line seperator.
+			*/
+			str=str.split("\r\n").join("\n");
+			str=str.split("\r").join("\n");
+			var lineContentArr:Array = str.split("\n");
+			
+			//bof of parsing the text.
+			if(lineContentArr== null ) {
+				logger.fatal("Rule File[{0}] Operation[parsing] has nothing in the file.", this._rulePath  );
+				return;
+			}
+			/* remove byte order mark */
+			if ( lineContentArr[0].match(new RegExp("^\xEF\xBB\xBF[.]+$") ) ) lineContentArr[0]=lineContentArr[0].substr(3);
+
+			var lineContent:String;
+			var res:int;
+			for( var line:int = 0; line<lineContentArr.length; ) {
+				lineContent= lineContentArr[line];
+				if ( parseEncoding( lineContent, line ) ) {
+					break;
+				}
+				++line;
+			}
+			//eof of parsing the text.
+			if( _attrMgr.encoding == null ) {
+				logger.fatal("Rule File[{0}] Operation[parsing] Error[no encoding specified] in file.",this._rulePath );
+				_attrMgr.encoding= InternalConstants.DEFAULTENCODING;
+			}
+			
+		}
+		
+		private function parseEncoding(lineContent:String, lineNumber:int):Boolean {
+			var result:String;
+			/* parse in the name of the character set used by the .dict and .aff */
+			if ( (result=parseStringAttribute("SET",lineContent)) != null ){
+				if ( _attrMgr.encoding != null ) {
+					//"error: line xxx: multiple definitions"
+					logger.error("Rule File[{0}] Operation[parsing] Error[multiple definitions] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}else{ 
+					result = getEncodingByString( result );
+					if ( result == "" ) {
+						logger.fatal("Rule File[{0}] Operation[parsing] Error[unsupported encoding] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent);
+						result = InternalConstants.DEFAULTENCODING;
+					}
+					_attrMgr.encoding = result;
+				}
+				return true;
+			}
+			return false;
+		}
+
+
+		private function parseMapTable( lineContent:String, lineContentArray:Array, lineNumber:int ) :int {
+			var res:int = 0;
+			if ( !testKeyString("MAP",lineContent)  )
+				return res;
+			var seperatorPattern:RegExp = /[\t ]+/;
+			if ( _attrMgr.mapFilterTable.length != 0 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[multiple definitions] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			/*
+			MAP number_of_map_definitions
+			MAP string_of_related_chars
+				We can define language-dependent information on characters that should be considered related (ie. nearer than other chars not in the set) in the affix file (.aff) by a character map table. With this table, Hunspell can suggest the right forms for words, which incorrectly choose the wrong letter from a related set more than once in a word. 
+			For example a possible mapping could be for the German umlauted ü versus the regular u; the word Frühstück really should be written with umlauted u's and not regular ones
+			MAP 1
+			MAP uü
+			word support in spell checking (forbidding generated compound words, if they are also simple words with typical fault). 
+			*/
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length < 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length < 2) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="MAP" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				var mapString:String =strArr[1];
+				/* special handling for the rule file include mixed-case mapping string:
+					MAP 5
+					MAP aáAÁ
+					MAP eéEÉ
+					MAP iíIÍ
+					MAP oóOÓ
+					MAP uúüUÚÜ
+				*/
+				var capaType:int = StringUtils.getCapType(mapString);
+				if ( capaType == InternalConstants.ALLCAP ||  capaType == InternalConstants.NOCAP ) {
+					_attrMgr.addMapFilter(mapString);
+				}else {
+					var upperStr:String="";
+					var lowerStr:String=""; 
+					for ( var i:int=0;i< mapString.length;++i ) {
+						if ( mapString.charAt(i) != mapString.charAt(i).toLocaleUpperCase() ) {
+							lowerStr+=mapString.charAt(i);
+						}else {
+							upperStr+=mapString.charAt(i);
+						}
+					}
+					_attrMgr.addMapFilter(upperStr);
+					_attrMgr.addMapFilter(lowerStr);
+				}
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+			
+		}
+		
+		private function parseReplaceTable( lineContent:String, lineContentArray:Array, lineNumber:int ) :int {
+			var res:int = 0;
+			if ( !testKeyString("REP",lineContent)  )
+				return res;
+			var seperatorPattern:RegExp = /[\t ]+/;
+			if ( _attrMgr.simpleFilterTable.length != 0 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			/*
+			REP number_of_replacement_definitions
+			REP what replacement
+			    We can define language-dependent phonetic information in the affix file (.aff) by a replacement table. 
+			    First REP is the header of this table and one or more REP data line are following it. With this table, 
+			    Hunspell can suggest the right forms for the typical faults of spelling when the incorrect form differs 
+			    by more, than 1 letter from the right form. For example a possible English replacement table definition 
+			    to handle misspelled consonants: 
+			REP 8
+			REP f ph
+			REP ph f
+			REP f gh
+			REP gh f
+			REP j dg
+			REP dg j
+			REP k ch
+			REP ch k
+			Replacement table is also usable in robust morphological analysis (accepting bad forms) or stricter compound 
+			word support in spell checking (forbidding generated compound words, if they are also simple words with typical fault). 
+			*/
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length != 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length != 3) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="REP" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				var matchString:String =strArr[1];
+				var replacement:String =strArr[2];
+				_attrMgr.addSimpleFilter(matchString,replacement);
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+		}
+		
+		/*---------parse phone table
+		Param: Line content, lince content array, and line number
+		Return: number of parsed lines
+		*/
+/*		private function parsePhoneTable( lineContent:String, lineContentArray:Array, lineNumber:int ) :int {
+			var res:int = 0;
+			if ( !testKeyString("PHONE",lineContent)  )
+				return res;
+			var seperatorPattern:RegExp = /[\t ]+/;
+			if ( _attrMgr.phoneTable ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			
+			PHONE number_of_phone_definitions
+			PHONE what replacement
+			PHONE uses a table-driven phonetic transcription algorithm borrowed from Aspell. It is useful for
+			languages with not pronunciation based orthography. You can add a full alphabet conversion and
+			other rules for conversion of special letter sequences. For detailed documentation see
+			http://aspell.net/man-html/Phonetic-Code.html. Note: Multibyte UTF-8 characters have not
+			worked with bracket expression yet. Dash expression has signed bytes and not UTF-8 characters
+			yet.
+			
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length != 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			//now parse the remaining lines
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length != 3) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="PHONE" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				var matchString:String =strArr[1];
+				var replacement:String =strArr[2];
+				_attrMgr.phoneTable.addPhoneticFilter(matchString,replacement);//TODO: edit this
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+		}
+*/		//---------parse phone table ends----//
+		
+		//---------parse conv table starts
+		private function parseConvTable( lineContent:String, lineContentArray:Array, lineNumber:int ) :int {
+			var res:int = 0;
+			var ioflag:Boolean;
+			var convTable:Array;
+			if(testKeyString("ICONV",lineContent)!=false){
+			//do for iconvtable	
+			ioflag=true;
+			convTable=_attrMgr.iconvFilterTable;
+			}
+			else if(testKeyString("OCONV",lineContent)!=false){
+			//do for oconvtable
+			ioflag=false;
+			convTable=_attrMgr.oconvFilterTable;
+			}
+			else return res;
+			
+			var seperatorPattern:RegExp = /[\t ]+/;
+			if ( (!convTable)||(convTable && convTable.length != 0 )) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			/*ICONV number_of_ICONV_definitions
+			ICONV pattern pattern2
+			Define input conversion table.
+			OCONV number_of_OCONV_definitions
+			OCONV pattern pattern2
+			Define output conversion table.
+			*/
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length != 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length != 3) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="REP" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				var matchString:String =strArr[1];
+				var replacement:String =strArr[2];
+				_attrMgr.addConvFilter(matchString,replacement,ioflag);//todo
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+		}
+		//--parse Convtable ends
+		//--parse BreakTable starts
+		private function parseBreakTable( lineContent:String, lineContentArray:Array, lineNumber:int ) :int {
+			var res:int = 0;
+			if( !testKeyString("BREAK",lineContent) )
+				return res;
+			
+			var seperatorPattern:RegExp = /[\t ]+/;
+			if ( _attrMgr && _attrMgr.breakTable && _attrMgr.breakTable.length != 0 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			/*
+			BREAK number_of_break_definitions
+			BREAK character_or_character_sequence
+			Define new break points for breaking words and checking word parts separately. Use ˆ and $ to
+			delete characters at end and start of the word. Rationale: useful for compounding with joining
+			character or strings (for example, hyphen in English and German or hyphen and n-dash in Hungarian).
+			Dashes are often bad break points for tokenization, because compounds with dashes may
+			contain not valid parts, too.) With BREAK, Hunspell can check both side of these compounds,
+			breaking the words at dashes and n-dashes:
+			BREAK 2
+			BREAK -
+			BREAK -- # n-dash
+			*/
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length != 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length != 2) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="BREAK" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+			if(_attrMgr.breakTable)	_attrMgr.breakTable.push(strArr[1]);
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+		}
+		//--parse Breaktable Endas
+		
+		private function parseAffix(lineContent:String, lineContentArray:Array, lineNumber:int ) : int {
+			var res:int = 0;
+			if ( !testKeyString("PFX",lineContent) && !testKeyString("SFX",lineContent) )
+				return res;
+			var seperatorPattern:RegExp = /[\t ]+/;
+			var slashInsidePattern:RegExp = /^(.+)\/(.+)$/
+			
+			var resStrArr:Array;
+			
+			/* 
+			Affix classes are signed with affix flags. The first line of an affix class definition is the header. The fields of an affix class header:
+			(0) Option name (PFX or SFX)
+			(1) Flag (name of the affix class)
+			(2) Cross product (permission to combine prefixes and suffixes). Possible values: Y (yes) or N (no)
+			(3) Line count of the following rules. 
+			*/
+			var strArr:Array = lineContent.split( seperatorPattern );
+			if ( strArr == null || strArr.length < 4 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			// piece 1 - is type of affix
+			var atype:int = (strArr[0]=="PFX") ? 0 : 1;
+			 // piece 2 - is affix char
+			var aflag:int = decodeFlag( strArr[1], this._attrMgr.flagMode );
+			// piece 3 - is cross product indicator 
+			var aPermission:Boolean = (strArr[2]=="Y") ? true : false;
+			// piece 4 - is number of affentries
+			var numberOfEntries:int = snp.parse(strArr[3]); 
+			var stripStr:String;
+			var affixStr:String;
+			var conditionsStr:String;
+			var morphStr:String;
+			var conditionPattern:RegExp;
+			var contclass:String;
+			
+			if ( numberOfEntries == 0 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				var warnFlag:Boolean = false;
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				/*
+				Fields of an affix rules:
+				(0) Option name
+				(1) Flag
+				(2) stripping characters from beginning (at prefix rules) or end (at suffix rules) of the word
+				(3) affix (optionally with flags of continuation classes, separated by a slash)
+				(4) condition.
+				Zero stripping or affix are indicated by zero. Zero condition is indicated by dot. Condition is a simplified, regular expression-like pattern, which must be met before the affix can be applied. (Dot signs an arbitrary character. Characters in braces sign an arbitrary character from the character subset. Dash hasn’t got special meaning, but circumflex (^) next the first brace sets the complementer character set.)
+				(5) Optional morphological fields separated by spaces or tabulators. 				
+				*/
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length < 5) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				// piece 1 - is type of affix
+				var aatype:int = (strArr[0]=="PFX") ? 0 : 1;
+				if ( aatype != atype ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				 // piece 2 - is affix char
+				var aaflag:int = decodeFlag( strArr[1],this._attrMgr.flagMode );
+				if ( aaflag != aflag ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				// piece 3 - is string to strip or 0 for null 
+				stripStr = strArr[2];
+				if ( stripStr == "0" ) stripStr="";
+				
+				/*complex affix bof*/
+				if ( (resStrArr=stripStr.match(slashInsidePattern)) != null ) {
+					stripStr = resStrArr[1];
+					warnFlag = true;
+					logger.warn("Rule File[{0}] Operation[parsing] Warn[complex affix] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				/*complex affix eof*/
+				
+				// piece 4 - is affix string or 0 for null
+				/*complex affix bof*/
+				if (strArr[3] && (resStrArr=strArr[3].match(slashInsidePattern)) != null ) //if contclass in Affix Rules
+				{
+					if(this._attrMgr && this._attrMgr.aliasfTable && this._attrMgr.aliasfTable.length>0)//if AF rule 
+					{
+						affixStr = resStrArr[1];
+						contclass=this._attrMgr.aliasfTable[parseInt(resStrArr[2],10)-1];
+					}
+					else// If not AF rule
+					{
+						affixStr =resStrArr[1];
+						contclass=decodeFlags(resStrArr[2],this._attrMgr.flagMode);
+						
+					}
+					
+					this._attrMgr.haveContClass=true;
+					
+					for(var i:int=0;i<contclass.length; i++ )//record the possible contclass in possible contclass array
+						this._attrMgr.contClasses[contclass.charCodeAt(i)]=true;
+				}
+				else
+				{
+					affixStr=strArr[3];
+					contclass=null;
+				}
+				if ( affixStr == "0" ) affixStr="";
+				if ( _attrMgr.ignoredChars != null ) StringUtils.removeIgnoredChars(affixStr, _attrMgr.ignoredChars );
+				/*complex affix eof*/
+
+
+				
+				// piece 5 - is the conditions descriptions
+				conditionsStr = strArr[4];
+				if ( conditionsStr.length == 0 ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				
+				//piece 6  morph information... ToDo....
+				morphStr = (strArr.length == 6) ? strArr[5]: "";
+			/*if(contclass && affixStr=="lit")	
+				for(var c:int=0;c<contclass.length;c++){
+				if(_attrMgr.flagMode== InternalConstants.FLAG_LONG)
+					trace(" contclasslong   "+c+"           " + String.fromCharCode(contclass.charCodeAt(c)>>8)+String.fromCharCode(contclass.charCodeAt(c)-((contclass.charCodeAt(c)>>8)<<8)));
+				else
+					trace(" contclassnormal   "+c+"           " + contclass[c]);
+			}*/
+				_attrMgr.addAffixEntry( aflag, stripStr, affixStr, conditionsStr, morphStr, aPermission, atype, contclass );
+				
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			
+			return (numberOfEntries);
+		}
+		
+		//-------parseAliasf
+		private function parseAliasf(lineContent:String, lineContentArray:Array, lineNumber:int ) : int {
+			var res:int = 0;
+			if ( !testKeyString("AF",lineContent))
+				return res;
+			var seperatorPattern:RegExp = /[\t ]+/;
+			var slashInsidePattern:RegExp = /^(.+)\/(.+)$/
+			
+			var resStrArr:Array;
+			
+			/* 
+			AF number_of_flag_vector_aliases
+			AF flag_vector
+			Hunspell can substitute affix flag sets with ordinal numbers in affix rules ( compression, see
+			makealias tool). First example with  compression:
+			3
+			hello
+			try/1
+			work/2
+			AF definitions in the affix file:
+			SET UTF-8
+			TRY esianrtolcdugmphbyfvkwzESIANRTOLCDUGMPHBYFVKWZ’
+			AF 2
+			AF A
+			AF AB
+			It is equivalent of the following dic file:
+			3
+			hello
+			try/A
+			work/AB
+			*/
+			var strArr:Array = lineContent.split(seperatorPattern);
+			if ( strArr == null || strArr.length != 2 ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			var numberOfEntries:int = snp.parse(strArr[1]); 
+			var parsedLines:int = 0;
+			lineNumber++;
+			while( lineNumber < lineContentArray.length && parsedLines<numberOfEntries ) {
+				lineContent = lineContentArray[lineNumber];
+				lineNumber++;
+				parsedLines++;
+				strArr = lineContent.split(seperatorPattern);
+				if ( strArr == null || (strArr.length != 2) ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				if ( strArr[0]!="AF" ) {
+					logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+				}
+				//Decode Flags and store as long numbers. In normal case without AF rule we do this step later. Here we are decoding and storing the flags.
+				var flags:String=decodeFlags(strArr[1],this._attrMgr.flagMode);
+				_attrMgr.aliasfTable.push(flags);
+			}
+			if ( parsedLines != numberOfEntries ) {
+				logger.error("Rule File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			}
+			return (numberOfEntries);
+		}
+		//--------parseAliasf
+		//------decodeflags
+		/*
+		* Squiggly is using utf16 by default...
+		* for utf8 string conversion,we need extra work later.
+		* we might also need a better toString() fuction for Flag_long and flag_num mode.
+		*/
+		private function decodeFlags(flags:String, flagMode:int):String {
+			var result:String="";
+			var i:int;
+			switch ( flagMode )  {
+				case InternalConstants.FLAG_LONG:
+					if ( (flags.length)%2 == 1 ) {
+						logger.error("Dictionary File[{0}] Operation[parsing] Error[decoding error] target flags:{1}",this._rulePath , flags );
+						throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID);
+					}
+					var len:int = flags.length/2;
+					for ( i = 0; i< len; ++i ) {
+						result +=  String.fromCharCode( ((flags.charCodeAt((i * 2))) << 8) + (flags.charCodeAt((i * 2 + 1))) );
+					}
+					break;
+				case InternalConstants.FLAG_NUM:
+					var strArr:Array = flags.split(",");
+					for ( i = 0;i< strArr.length;++i) {
+						var num:Number = snp.parse(strArr[i]);
+						if ( num >= InternalConstants.DEFAULTFLAGS ) {
+							logger.error("Dictionary File[{0}] Operation[parsing] Error[decoding error] target flags:{1}",this._rulePath , flags );
+						}
+						result += String.fromCharCode(num);
+					}
+					break;
+				case InternalConstants.FLAG_UNI:
+					result = flags;
+					break;
+				default:
+					result = flags;
+					break;
+			}
+			return result;
+		}
+//-----------decode flags ends
+		
+		
+		private function decodeFlag( flagString:String, flag_mode:int=InternalConstants.FLAG_CHAR  ) : int {
+			var s:int;
+			var i:int;
+			switch ( flag_mode ) {
+				case InternalConstants.FLAG_LONG:
+					if ( flagString.length != 2 ) {
+						logger.error("Rule File[{0}] Operation[decodeFlag] Error[Unknown Flags] The length of flag id {1} is not equal 2.",this._rulePath , flagString);
+					}
+					s = ( flagString.charCodeAt(0) << 8) + flagString.charCodeAt(1);
+					break;
+				case InternalConstants.FLAG_NUM:
+					i = snp.parse(flagString);
+					if (i >= InternalConstants.DEFAULTFLAGS) {
+						logger.error("Rule File[{0}] Operation[decodeFlag] Error[Unknown Flags] flag id {1} is too large (max: {2})",this._rulePath , i.toString(),InternalConstants.DEFAULTFLAGS.toString() );
+					}
+					s = i;
+					break;
+				case InternalConstants.FLAG_UNI: // utf-8
+				default:
+					s = flagString.charCodeAt(0);
+			}
+			return s;
+		}
+
+		private function parseFlagMode(lineContent:String, lineNumber:int):Boolean {
+			var result:String;
+			/* parse in the name of the character set used by the .dict and .aff */
+			if ( (result=parseStringAttribute("FLAG",lineContent)) != null ){
+	            if (result == "long") _attrMgr.flagMode = InternalConstants.FLAG_LONG;
+	            if (result == "num") _attrMgr.flagMode = InternalConstants.FLAG_NUM;
+	            if (result == "UTF-8") _attrMgr.flagMode = InternalConstants.FLAG_UNI;
+	            if ( result == "char" ) _attrMgr.flagMode = InternalConstants.FLAG_CHAR;
+				return true;
+			}
+			return false;
+		}
+
+
+		private function parseAttribute(lineContent:String, lineNumber:int):Boolean {
+			var result:String;
+			
+			/* parse in the name of the character set used by the .dict and .aff */
+			if ( parseFlagMode(lineContent,lineNumber) ){
+				return true;
+			}
+			
+			 /* parse in the keyboard string */
+			if ( (result=parseStringAttribute("KEY",lineContent)) != null ){
+				_attrMgr.keyString = result;
+				return true;
+			}
+			
+			/* parse in the try string */
+			if ( (result=parseStringAttribute("TRY",lineContent)) != null ){
+				if ( _attrMgr.tryString != null ) {
+					//"error: line %d: multiple definitions\n"
+					throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID); 
+				}else _attrMgr.tryString = result;
+				return true;
+			}
+			
+			/* parse in the name of the character set used by the .dict and .aff */
+			if ( (result=parseStringAttribute("SET",lineContent)) != null ){
+				return true;
+			}
+			
+			/* parse in the noSuggest flag */
+			if ( (result=parseStringAttribute("NOSUGGEST",lineContent)) != null ){
+			//	_attrMgr.noSuggest = result.charCodeAt(0); //Depreceated old function, had to be changed for supporting FLAG_LONG
+				_attrMgr.noSuggest = decodeFlag(result, this._attrMgr.flagMode);
+
+				return true;
+			}
+			
+			/* parse in the flag used by forbidden words */
+			if ( (result=parseStringAttribute("FORBIDDENWORD",lineContent)) != null ){
+				//_attrMgr.forbiddenWord = result.charCodeAt(0);//Depreceated old function, had to be changed for supporting FLAG_LONG
+				_attrMgr.forbiddenWord = decodeFlag(result, this._attrMgr.flagMode);
+
+				return true;
+			}
+
+			 /* parse in the ignored characters (for example, Arabic optional diacretics charachters */
+			if ( (result=parseStringAttribute("IGNORE",lineContent)) != null ){
+				if ( _attrMgr.ignoredChars != null ) {
+					//"error: line %d: multiple definitions\n"
+					throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID); 
+				}else _attrMgr.ignoredChars = result;
+				return true;
+			}
+
+			/* parse in the extra word characters */
+			if ( (result=parseStringAttribute("WORDCHARS",lineContent)) != null ){
+				if ( _attrMgr.wordChars != null ) {
+					//"error: line %d: multiple definitions\n"
+					throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID); 
+				}else _attrMgr.wordChars = result;
+				return true;
+			}
+			
+			/* parse in the language for language specific codes */
+			if ( (result=parseStringAttribute("LANG",lineContent)) != null ){
+				if ( _attrMgr.languageCode != null ) {
+					//"error: line %d: multiple definitions\n"
+					throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID); 
+				}else {
+					_attrMgr.languageCode = result;
+					//langnum = get_lang_num(lang);
+				}
+				return true;
+			}
+			
+			/* parse in the version */
+			if ( (result=parseStringAttribute("VERSION",lineContent)) != null ){
+				_attrMgr.version = result;
+				return true;
+			}
+
+			if ( (result=parseStringAttribute("MAXNGRAMSUGS",lineContent)) != null ){
+				_attrMgr.maxNgramSuggestions = snp.parse(result);
+				return true;
+			}
+			
+			if ( testKeyString("NOSPLITSUGS",lineContent) ) {
+				_attrMgr.nosplitSuggestions = 1;
+			}
+			
+			if ( testKeyString("SUGSWITHDOTS",lineContent) ) {
+				_attrMgr.suggestionsWithDots = 1;
+			}
+			
+			if ( testKeyString("FULLSTRIP",lineContent) ) {
+				_attrMgr.fullStrip = 1;
+			}
+			/* parse in the noSuggest flag */
+			if ( (result=parseStringAttribute("KEEPCASE",lineContent)) != null ){
+				//_attrMgr.keepCase = result.charCodeAt(0);//Depreceated old function, had to be changed for supporting FLAG_LONG
+				_attrMgr.keepCase = decodeFlag(result, this._attrMgr.flagMode);
+				return true;
+			}
+			
+			/*parse in the CIRCUMFIX flag*/
+			if ( (result=parseStringAttribute("CIRCUMFIX",lineContent)) != null ){
+			//	_attrMgr.circumfix =result.charCodeAt(0);//Depreceated old function, had to be changed for supporting FLAG_LONG
+				_attrMgr.circumfix =decodeFlag(result, this._attrMgr.flagMode);
+				return true;
+			}
+			/*parse in the NEEDAFFIX flag*/
+			if ( (result=parseStringAttribute("NEEDAFFIX",lineContent)) != null ){
+				//_attrMgr.needAffix = result.charCodeAt(0); ////Depreceated old function, had to be changed for supporting FLAG_LONG
+				_attrMgr.needAffix = decodeFlag(result, this._attrMgr.flagMode);
+				return true;
+			}
+			
+		return false;
+		}
+		
+		private function parseStringAttribute(key:String, lineContent:String):String {
+			if ( lineContent == null || key == null ) return null;
+			var keyPattern:RegExp = new RegExp("^"+key+"[\\t ]+(.+)$");
+			var parseArr:Array;
+			if ( (parseArr=lineContent.match(keyPattern)) != null ) {
+				return parseArr[1];
+			}		
+			return null;
+		}
+		
+		private function testKeyString(key:String,lineContent:String):Boolean {
+			if ( key == null ) return false;
+			var keyPattern:RegExp = new RegExp("^"+key+".*$");
+			return keyPattern.test( lineContent );
+		}
+
+		private function isCommentOrEmpty(lineContent:String):Boolean{
+			var str:String = lineContent;
+			str = StringUtils.trim( lineContent);
+			if ( str == "" ) return true;
+			if ( testKeyString("#",str) ) return true;
+			return false;
+		}
+
+		private function getEncodingByString(key:String):String {
+			var result:String = "";
+			var keyEncodingTable:Object = {"UTF-8":"utf-8", "ISO8859-1":"iso-8859-1","ISO8859-2":"iso-8859-2","ISO8859-3":"iso-8859-3",
+			"ISO8859-4":"iso-8859-4","ISO8859-5":"iso-8859-5","ISO8859-6":"iso-8859-6","ISO8859-7":"iso-8859-7","ISO8859-8":"iso-8859-8",
+			"ISO8859-9":"iso-8859-9", "ISO8859-15":"iso-8859-15", "KOI8-R":"koi8-r", "KOI8-U":"koi8-u", "microsoft-cp1251":"windows-1251", 
+			"ISCII-DEVANAGARI":"x-iscii-de"};
+			var unsupportedTable:Object = {"ISO8859-10":"", "ISO8859-13":""};
+			if ( key == null ) return InternalConstants.DEFAULTENCODING;
+			
+			if ( keyEncodingTable[key] == undefined || keyEncodingTable[key] == "" ) return result;
+			result = keyEncodingTable[key];
+			
+			return result;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/MathUtils.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/MathUtils.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/MathUtils.as
new file mode 100644
index 0000000..2c79756
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/MathUtils.as
@@ -0,0 +1,66 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	public class MathUtils
+	{
+		/**
+		 *  Return next prime; assume N >= 10 
+		 */
+		public static function nextPrime( N:int ):int
+		{
+			var i:int;
+			var continueFlag:Boolean;
+			if( N % 2 == 0 )
+				N++;
+			for( ; ; N += 2 )
+			{
+				continueFlag = false;
+				for( i = 3; i * i <= N; i += 2 )
+					if( N % i == 0 ) {
+						continueFlag = true;    //Sorry about this!
+						break;
+					}
+				if ( continueFlag ) continue;
+				return N;
+			}
+			return -1; // failure branch... it should never happen.
+		}
+
+		/**
+		 * Rounds a number to a specific number of decimal places.
+		 */
+		public static function roundPrecision(number:Number, precision:int=0):Number
+		{
+			var places:Number = Math.pow(10, precision);
+			return Math.round(places * number) / places;
+		}
+
+		/**
+		 * Generates a random number between two number values.
+		 */
+		public static function randomBetween(min:Number=0, max:Number=99999999, precision:int=0):Number
+		{
+			return roundPrecision(Math.random() * (max - min) + min, precision);
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/RefObject.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/RefObject.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/RefObject.as
new file mode 100644
index 0000000..ef1a99d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/RefObject.as
@@ -0,0 +1,36 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	public class RefObject
+	{
+		private var _ref:int;
+		public function RefObject(value:int) {
+			this._ref = value;
+		}
+		public function set ref(v:int):void {
+			this._ref = v;
+		}
+		public function get ref():int {
+			return this._ref;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SimpleNumberParser.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SimpleNumberParser.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SimpleNumberParser.as
new file mode 100644
index 0000000..29bdc4b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SimpleNumberParser.as
@@ -0,0 +1,54 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	/*
+	 * A simple number parsing class...
+	 */
+	public class SimpleNumberParser
+	{
+		private var numberPattern:RegExp = /^((\d+,?)*\d+)?\.?\d*$|^[-+]?\d+\.?\d*[eE]{1}[-+]?\d+$/;
+		private var negativePattern:RegExp = /^-[ ]?([0-9\.,]+)$|^([0-9\.,]+)[ ]?-$|^\([ ]?([0-9\.,]+)[ ]?\)$/;
+		private var _decimalSymbol:String, _grouppingSymbol:String;
+		
+		public function SimpleNumberParser(decimalSymbol:String=".", grouppingSymbol:String=",")
+		{
+			this._decimalSymbol = decimalSymbol; this._grouppingSymbol = grouppingSymbol;
+		}
+		
+		public function parse(inputString:String):Number {
+			var neg:int = 1;
+			inputString= inputString.split(_decimalSymbol).join("."); 
+			inputString= inputString.split(_grouppingSymbol).join(",");
+			inputString= StringUtils.trim(inputString);
+			if ( negativePattern.test(inputString) ) {
+				var result:Array = inputString.match( negativePattern );
+				for ( var i:int = 1; i < result.length; i++ )
+					if ( result[i]!= undefined ) break;
+				inputString= result[i];
+				neg=-1;
+			}
+			if ( !numberPattern.test( inputString ) ) return NaN;
+			inputString= inputString.split(_grouppingSymbol).join(""); 
+			return (new Number(inputString))*neg;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SquigglyDictionaryLoader.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SquigglyDictionaryLoader.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SquigglyDictionaryLoader.as
new file mode 100644
index 0000000..e97000c
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SquigglyDictionaryLoader.as
@@ -0,0 +1,369 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	import com.adobe.linguistics.spelling.core.LinguisticRule;
+	import com.adobe.linguistics.spelling.core.SquigglyDictionary;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.error.*;
+	import com.adobe.linguistics.spelling.core.logging.*;
+	
+	import flash.errors.IllegalOperationError;
+	import flash.events.ErrorEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IOErrorEvent;
+	import flash.events.SecurityErrorEvent;
+	import flash.net.URLRequest;
+	import flash.utils.*;
+	public class SquigglyDictionaryLoader extends EventDispatcher
+	{
+		private var _dict:SquigglyDictionary;
+		private var _dictionaryPath:String;
+		private var _attrMgr:LinguisticRule;
+
+
+		private var snp:SimpleNumberParser = new SimpleNumberParser();
+
+		//setup logger for sending message.
+		private var className:String = flash.utils.getQualifiedClassName(this).split("::").join(".");
+		private var logger:ILogger = Log.getLogger( className );
+		//vars shifted up
+        private var wordList:Array;
+		private var dp:String;//description;
+		private var ts:String;
+		private var ap:String;
+		private var flags:String;
+		
+		private var dpPattern1:RegExp; 	//patterns to split rule line into fileds according to new morphological field separator
+		private var dpPattern2:RegExp;	//patterns to split rule line into fileds according to old morphological field separator
+		private var tsPattern1:RegExp;	//extracts the affix string
+		private var strArr:Array;
+		private var lineContent:String;
+		private var totalPart:int;
+		private var delay:int;
+		//vars shifted up
+		
+		//variables added to accomodate property
+		private var _enableDictionarySplit:Boolean;
+		private var _wordsPerDictionarySplit:int;
+		
+		public function SquigglyDictionaryLoader()
+		{
+			_dict = null;
+			_dictionaryPath = null;
+			_attrMgr = null;
+			dpPattern1= /^(.+)[ \t]+.{2}:(.+)$/ ; 	//patterns to split rule line into fileds according to new morphological field separator
+			dpPattern2= /^(.+)[\t]{1}(.+)$/ ; 		//patterns to split rule line into fileds according to old morphological field separator
+			tsPattern1= /^(.*[^\\])\/(.+)$/ ; 
+			delay=InternalConstants.DICT_LOAD_DELAY; //the timeout period between two parts 10 ms
+		}
+		
+		public function set linguisticRule(value:LinguisticRule):void {
+			this._attrMgr = value;
+		}
+		
+		public function get linguisticRule():LinguisticRule {
+			return this._attrMgr;
+		}
+		
+		public function load(dictionaryURL:String,enableDictionarySplit:Boolean,wordsPerDictionarySplit:int):void {
+			if ( dictionaryURL == null ) {
+				throw new IllegalOperationError("load function did not receive two valid URLs.");
+			}
+			_dictionaryPath = dictionaryURL;
+			_enableDictionarySplit=enableDictionarySplit;
+			_wordsPerDictionarySplit=wordsPerDictionarySplit;
+			var request:URLRequest = new URLRequest( _dictionaryPath );
+			var dloader:DictionaryLoader = new DictionaryLoader(request);
+			dloader.addEventListener(Event.COMPLETE,loadDictionaryComplete);
+			dloader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+			dloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+			
+		}
+
+		//Private method to dispatch an error event.
+		private function handleError(evt:Event):void {
+			bounceEvent(evt);
+		}
+		private function bounceEvent(evt:Event):void {
+			dispatchEvent(evt.clone());
+		}
+
+
+		public function get squigglyDictionary():SquigglyDictionary {
+			return  _dict;
+		}
+		
+		private function loadDictionaryComplete(evt:Event):void {
+			_dict = new SquigglyDictionary(_attrMgr);
+
+			var bytes:ByteArray = evt.target.data;
+			//trace("load complete handler: "+getTimer()+" "+bytes.bytesAvailable);
+			var charSet:String;
+			if ( _attrMgr ) {
+				charSet = _attrMgr.encoding;
+			}else {
+				charSet = InternalConstants.DEFAULTENCODING;
+			}
+			var str:String = 	bytes.readMultiByte(bytes.length, charSet);
+			//trace("Bytes read at: "+getTimer());
+
+			/*
+			In DOS, a line break is a single '\n'.
+			In Unix, a line break is the sequence '\r\n'.
+			In MAC, a line break is a single '\r'.
+			Correct me if I'm wrong.
+			so step 1:
+			replace "\r\n" with "\n"
+			step 2:
+			replace "\r" with "\n";
+			finally ,we get "\n" line seperator.
+			*/
+			str=str.split("\r\n").join("\n");
+			str=str.split("\r").join("\n");
+			wordList= str.split("\n");
+			//bof of parsing the text.
+			//trace("Wordlist length: "+wordList.length);
+			if(wordList== null ) {
+				logger.error("Dictionary File[{0}] Operation[parsing] Error[corrupt data]",this._dictionaryPath);
+			}
+			if(wordList.length== 1){
+				logger.error("Dictionary File[{0}] Operation[parsing] Error[corrupt data]",this._dictionaryPath );
+//				logger.error("Dictionary File[{0}] Operation[parsing] Error[corrupt data] Line Number:{1}, Content:{2}",this._rulePath , (lineNumber+1).toString(),lineContent );
+			} 
+			//fix for 	Bug #: 	2855795 now if greater load to a max of wordList.length
+			if(wordList.length<this._wordsPerDictionarySplit){
+				this._wordsPerDictionarySplit=wordList.length;				
+			}
+			
+			/* remove byte order mark */
+			if ( wordList[0].match(new RegExp("^\xEF\xBB\xBF[.]+$") ) ) wordList[0]=wordList[0].substr(3);
+			var snp:SimpleNumberParser = new SimpleNumberParser();
+			/* get the table size */
+			var tablesize:int = snp.parse(wordList[0]);
+			if (tablesize == 0) throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID);
+			
+			//trace("Before parsing: "+getTimer());
+			
+			if(this._enableDictionarySplit ){
+				setTimeout(loadWithTimeouts,1,1);//go to loadWithTimeouts
+			}
+			else
+			{	
+				setTimeout(loadWithoutTimeouts,1,1);//directly go to finish. This will cause words to load from 1 to wordList.length
+			}
+			
+		}
+	
+		private function loadWithTimeouts(part:int):void	{
+			for( var line:int = part; line<part+(this._wordsPerDictionarySplit)-1; ++line) { 
+				lineContent = wordList[line];
+				/* : is the new morphological field separator */
+				if ( (strArr = lineContent.match(dpPattern1)) != null ) {
+					dp=strArr[2];
+					ts = strArr[1];
+				/* tabulator is the old morphological field separator */
+				}else if ( (strArr = lineContent.match(dpPattern2)) != null ) {
+					ts = strArr[1];
+					dp=strArr[2];
+				}else {
+					ts = lineContent;//so ts has the word and dp has morphological desc
+					dp = null;
+				}
+				
+				ts= StringUtils.trim(ts);
+				if( dp != null ) dp= StringUtils.trim(dp);
+				// eof: split each line into word and morphological description
+
+				// bof:split each line into word and affix char strings
+				/*
+				"\/" signs slash in words (not affix separator)
+				"/" at beginning of the line is word character (not affix separator)
+				*/
+				if ( (strArr = ts.match(tsPattern1))!= null ) {
+					ap = strArr[2]; 
+					ts = strArr[1];
+					ts = ts.split('\\/').join('/');	/* replace "\/" with "/" */
+					if(_attrMgr){
+						if(_attrMgr.aliasfTable && _attrMgr.aliasfTable.length>0)
+						{ 
+						flags=_attrMgr.aliasfTable[parseInt(ap,10)-1];
+						}
+						else
+						{
+						flags = decodeFlags( ap, _attrMgr.flagMode);
+						}
+					}
+/*	
+// Todo, will remove this comments after we have complex-affix support and compound-word support.
+            if (aliasf) {
+                int index = atoi(ap + 1);
+                al = get_aliasf(index, &flags, dict);
+                if (!al) {
+                    HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n", dict->getlinenum());
+                    *ap = '\0';
+                }
+            } else {
+                al = decode_flags(&flags, ap + 1, dict);
+                flag_qsort(flags, 0, al);
+            }
+*/
+				}else {
+					ap=null;
+					flags=null;
+				}
+				// eof:split each line into word and affix char strings
+				//trace(line+" WORD:"+ts);
+				_dict.addWord( ts, flags, dp );			
+		}
+				
+				if(line+(this._wordsPerDictionarySplit)>=wordList.length)//Last part reached.
+				{
+					setTimeout(loadWithoutTimeouts,delay,line);//the last part left which is less than wordsPerDictionarySplit is loaded w/o Timeouts
+				}
+				else
+				{
+				setTimeout(loadWithTimeouts,delay, line);//get delay of 10 ms
+				}
+			// } //loop ends
+			//eof of parsing the text.
+			//function ends here
+		}
+		
+		/* Squiggly function to end Asynchronous looping
+		*
+		*
+		*/
+		private function loadWithoutTimeouts(line:int):void
+		{
+			for( ; line<wordList.length; ++line) {
+				
+				// bof: split each line into word and morphological description 
+				lineContent = wordList[line];
+				/* : is the new morphological field separator */
+				if ( (strArr = lineContent.match(dpPattern1)) != null ) {
+					dp=strArr[2];
+					ts = strArr[1];
+					/* tabulator is the old morphological field separator */
+				}else if ( (strArr = lineContent.match(dpPattern2)) != null ) {
+					ts = strArr[1];
+					dp=strArr[2];
+				}else {
+					ts = lineContent;
+					dp = null;
+				}
+				ts= StringUtils.trim(ts);
+				if( dp != null ) dp= StringUtils.trim(dp);
+				// eof: split each line into word and morphological description
+				
+				// bof:split each line into word and affix char strings
+				/*
+				"\/" signs slash in words (not affix separator)
+				"/" at beginning of the line is word character (not affix separator)
+				*/
+				if ( (strArr = ts.match(tsPattern1))!= null ) {
+					ap = strArr[2]; 
+					ts = strArr[1];
+					ts = ts.split('\\/').join('/');	/* replace "\/" with "/" */
+					if(_attrMgr)
+					{
+						if(_attrMgr.aliasfTable && _attrMgr.aliasfTable.length>0)
+						{
+						flags=_attrMgr.aliasfTable[parseInt(ap,10)-1];
+						}
+						else
+						{
+						flags = decodeFlags( ap, _attrMgr.flagMode);
+						}
+					}
+					/*
+					// Todo, will remove this comments after we have complex-affix support and compound-word support.
+					if (aliasf) {
+					int index = atoi(ap + 1);
+					al = get_aliasf(index, &flags, dict);
+					if (!al) {
+					HUNSPELL_WARNING(stderr, "error: line %d: bad flag vector alias\n", dict->getlinenum());
+					*ap = '\0';
+					}
+					} else {
+					al = decode_flags(&flags, ap + 1, dict);
+					flag_qsort(flags, 0, al);
+					}
+					*/
+				}else {
+					ap=null;
+					flags=null;
+				}
+				// eof:split each line into word and affix char strings
+				//trace("WORD2:"+ts);
+				_dict.addWord( ts, flags, dp );			
+			}
+			//trace("After Parsing: "+getTimer());
+			logger.info("Dictionary File[{0}] Operation[parsing] Total Lines:{1}, Unrecognized Lines:{2}", this._dictionaryPath ,wordList.length.toString(), 0  );
+			
+			dispatchEvent(new Event(Event.COMPLETE));
+		}
+		
+		
+
+		/*
+		 * Squiggly is using utf16 by default...
+		 * for utf8 string conversion,we need extra work later.
+		 * we might also need a better toString() fuction for Flag_long and flag_num mode.
+		 */
+		private function decodeFlags(flags:String, flagMode:int):String {
+			var result:String="";
+			var i:int;
+			switch ( flagMode )  {
+				case InternalConstants.FLAG_LONG:
+				if ( (flags.length)%2 == 1 ) {
+					logger.error("Dictionary File[{0}] Operation[parsing] Error[decoding error] target flags:{1}",this._dictionaryPath , flags );
+					throw new ContentError(ErrorTable.CONTENTPARSINGERROR_MSG,ErrorTable.CONTENTPARSINGERROR_ID);
+				}
+				var len:int = flags.length/2;
+				for ( i = 0; i< len; ++i ) {
+					result +=  String.fromCharCode( ((flags.charCodeAt((i * 2))) << 8) + (flags.charCodeAt((i * 2 + 1))) );
+				}
+				break;
+				case InternalConstants.FLAG_NUM:
+				var strArr:Array = flags.split(",");
+				for ( i = 0;i< strArr.length;++i) {
+					var num:Number = snp.parse(strArr[i]);
+					if ( num >= InternalConstants.DEFAULTFLAGS ) {
+						logger.error("Dictionary File[{0}] Operation[parsing] Error[decoding error] target flags:{1}",this._dictionaryPath , flags );
+					}
+					result += String.fromCharCode(num);
+				}
+				break;
+				case InternalConstants.FLAG_UNI:
+				result = flags;
+				break;
+				default:
+				result = flags;
+				break;
+			}
+			return result;
+		}
+
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/StringUtils.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/StringUtils.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/StringUtils.as
new file mode 100644
index 0000000..63dba22
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/StringUtils.as
@@ -0,0 +1,333 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	public final class StringUtils
+	{
+		
+	    public static function isWhiteSpace( ch:Number ):Boolean {
+	    	// '\r' || '\n' || '\f' || '\t' || ' ' 
+	    	
+	    	return ch == 32 || 
+	    	ch == 32 || 
+	    	ch == 32 || 
+	    	ch == 32 || 
+	    	ch == 32; 
+	    }
+	    public static function isWhiteSpace2( ch:String ):Boolean {
+	    	// '\r' || '\n' || '\f' || '\t' || ' ' 
+	    	
+	    	return ch == '\r' || 
+	    	ch == '\n' || 
+	    	ch == '\f' || 
+	    	ch == '\t' || 
+	    	ch == ' '; 
+	    }
+    
+	    public static function trim( original:String ):String {
+	    	var i:int;
+	    	var start:int=0, end:int=original.length;
+	    	for ( i=0; (i< original.length) && isWhiteSpace(original.charCodeAt(i)) ; ++i ) {
+	    		start++;
+	    	}
+	    	for ( i=end-1; (i>=0) && isWhiteSpace(original.charCodeAt(i)) ; --i) {
+	    		end--;
+	    	}
+	    	return original.substring(start,end);
+	    }
+	    
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+	    public static function trim2( original:String ):String {
+
+	      var characters:Array = original.split( "" );
+	      for ( var i:int = 0; i < characters.length; i++ ) {
+	        if ( isWhiteSpace2( characters[i] ) ) {
+	          characters.splice( i, 1 );
+	          i--;
+	        } else {
+	          break;
+	        }
+	      }
+	      for ( i = characters.length-1; i >= 0; i-- ) {
+	      	if (isWhiteSpace2( characters[i] )) {
+	      		characters.splice( i, 1 );
+	      	}else {
+	      		break;
+	      	}
+	      }
+	      return characters.join("");
+	    }
+	    
+	    /*
+	     * ideally, this function shouldn't be here, we should always get a word without any ill-formed character. 
+	     * ToDo, will create a normalization class in next release....
+	     * Need revisit this function.
+	     */
+	    public static var curlyQuotePattern:RegExp = /[‘’]/;
+	    public static function normalize( value:String ):String {
+	    	var result:String;
+	    	if ( (value.indexOf("‘") == -1) && (value.indexOf("’") == -1) ) return value;
+	    	result = value.replace(curlyQuotePattern,"'");
+	    	return result;
+	    	
+	    }
+	    
+		public static function reverseString(str:String):String {
+			var sTmp:String="";
+			for ( var i:int= str.length -1 ; i >=0 ; i-- ) 
+				sTmp+=str.charAt(i);
+			return sTmp;
+		}
+		
+	    public static function sort(str:String, descending:Boolean= false):String {
+	    	if ( (str==null) || (str.length<=1) ) 
+	    		return str;
+	    	var chars:Array = str.split("");
+	    	if ( descending )
+	    		chars.sort(Array.DESCENDING);
+	    	else
+	    		chars.sort();
+	    	return chars.join("");	
+	    }
+
+		public static function removeIgnoredChars(word:String, ignoreChars:String ) :String {
+			if ( ignoreChars == null || word == null ) return word;
+			for ( var i:int = 0; i< ignoreChars.length ; ++i ) {
+				word.split(ignoreChars[i]).join("");
+			}
+			return word;
+		}
+
+		public static function makeInitCap(word:String):String {
+			return word.charAt(0).toLocaleUpperCase() + word.substr(1);
+		}
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+	    public static function getCapType1(word:String):int {
+			// now determine the capitalization type of the first nl letters
+			var ncap:int = 0;
+			var nneutral:int = 0;
+			var firstcap:int = 0;
+			// Potential improvment 1:
+			// It could be updated to user gslib StringUtils class in the future( after we have argo player 10.1 public). It is better for locale correction.
+			// at that time, we should consider about german language sharp SS -> beta case... the only case for changing the string length.
+			// Potential improvement 2:
+			// Using a hard code mapping table to convert the string to lowercase or uppercase. It is better for perfermance...
+			
+			if ( word == null || word=="" ) return InternalConstants.NOCAP;
+
+			var lowerStr:String = word.toLocaleLowerCase();
+			var upperStr:String = word.toLocaleUpperCase();
+
+			for ( var i:int = 0; i < word.length; ++i ) {
+				if ( upperStr.charCodeAt(i) == lowerStr.charCodeAt(i) ) 
+					nneutral++;
+				else {
+					if ( word.charCodeAt(i) == upperStr.charCodeAt(i) )
+						ncap++;
+				}
+			}
+			
+			if (ncap) {
+				if ( word.charCodeAt(0) == upperStr.charCodeAt(0) && upperStr.charCodeAt(0) != lowerStr.charCodeAt(0) )
+					firstcap = 1;
+			}
+
+			// now finally set the captype
+			if (ncap == 0) {
+				return InternalConstants.NOCAP;
+			} else if ((ncap == 1) && firstcap) {
+				return InternalConstants.INITCAP;
+			} else if ((ncap == word.length) || ((ncap + nneutral) == word.length)) {
+				return InternalConstants.ALLCAP;
+			} else if ((ncap > 1) && firstcap) {
+				return InternalConstants.HUHINITCAP;
+			}
+			return InternalConstants.HUHCAP;			
+	    }
+
+	    public static function getCapType(word:String):int {
+			// now determine the capitalization type of the first nl letters
+			var ncap:int = 0;
+			var nneutral:int = 0;
+			var firstcap:int = 0;
+			// Potential improvment 1:
+			// It could be updated to user gslib StringUtils class in the future( after we have argo player 10.1 public). It is better for locale correction.
+			// at that time, we should consider about german language sharp SS -> beta case... the only case for changing the string length.
+			// Potential improvement 2:
+			// Using a hard code mapping table to convert the string to lowercase or uppercase. It is better for perfermance...
+			
+			if ( word == null || word=="" ) return InternalConstants.NOCAP;
+			var lowerStr:String = word.toLocaleLowerCase();
+			var upperStr:String = word.toLocaleUpperCase();
+			//trying to find if non word characters are present
+			/*var nonWordCharRegex:RegExp = /\b\w+\b/;
+			var resNonWord:Array = word.match( nonWordCharRegex);
+			if(word==resNonWord[0]) then return 
+			trace("the word: "+resNonWord[0]);
+			trace("cosdfasdfnd: "+(word==resNonWord[0])+" Word "+word);*/
+			//var testWord:String= word;
+			
+			//var nonWordIndex:int= word.search(containsNonWordCharRegex);
+			//trace("**NonwordIndex : "+nonWordIndex+" Word: "+word);
+			//if(nonWordIndex!=-1) 
+			
+			if ( word == lowerStr ) return InternalConstants.NOCAP;
+			if ( word == upperStr ) return InternalConstants.ALLCAP;
+			if ( upperStr == lowerStr ) return InternalConstants.NOCAP;
+			if ( word.charCodeAt(0) == upperStr.charCodeAt(0) && upperStr.charCodeAt(0) != lowerStr.charCodeAt(0) ) {
+				ncap = 1;
+				for ( var i:int = 1; i < word.length; ++i ) {
+					if ( word.charCodeAt(i) == upperStr.charCodeAt(i) && upperStr.charCodeAt(i) != lowerStr.charCodeAt(i) ) {
+						ncap++;
+						break;
+					}
+				}
+				if ( ncap == 1 )
+					return InternalConstants.INITCAP;
+				else 
+					return InternalConstants.HUHINITCAP;
+			}else {
+		    	return InternalConstants.HUHCAP;
+			}
+	
+	    }
+	    
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error correction. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+	    static public function lcs1(a:String, b:String):String {
+	    	var aSub:String = a.substr(0,a.length-1);
+	    	var bSub:String = b.substr(0, b.length -1 );
+	    	if ( a.length == 0 || b.length == 0 ) {
+	    		return "";
+	    	}else if ( a.charAt(a.length-1) == b.charAt(b.length-1) ) {
+	    		return lcs1(aSub,bSub) + a.charAt(a.length-1);
+	    	}else {
+	    		var x:String = lcs1(a,bSub);
+	    		var y:String = lcs1(aSub,b);
+	    		return (x.length > y.length) ? x: y;
+	    	}
+	    }
+
+		/*
+		 * Longest common subsequence problem
+		 * From Wikipedia, the free encyclopedia
+		 * Jump to: navigation, search
+		 * Not to be confused with longest common substring problem.
+		 * The longest common subsequence (LCS) problem is to find the longest subsequence 
+		 * common to all sequences in a set of sequences (often just two). It is a classic computer 
+		 * science problem, the basis of diff (a file comparison program that outputs the differences 
+		 * between two files), and has applications in bioinformatics.
+		 * 
+		 * URL: http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
+		 */
+		static public function lcs(a:String, b:String):String {
+			var lengths:Array = new Array(a.length+1);
+			var i:int,j:int, x:int,y:int;
+			for ( i = 0 ; i< a.length+1; ++i ) {
+				lengths[i] = new Array(b.length+1);
+				for ( j=0; j< b.length+1; ++j) 
+					lengths[i][j]=0;
+			}
+			// row 0 and column 0 are initialized to 0 already
+			for ( i=0;i< a.length; ++i ) 
+				for( j=0;j<b.length; ++j)
+					if ( a.charAt(i) == b.charAt(j) )
+						lengths[i+1][j+1] = lengths[i][j] + 1;
+					else
+						 lengths[i+1][j+1] = Math.max(lengths[i+1][j], lengths[i][j+1]);
+			// read the substring out from the matrix
+			var res:String="";
+			for ( x = a.length,y=b.length; x!=0 && y!=0; ) {
+				if (lengths[x][y] == lengths[x-1][y])
+					x--;
+				else if ( lengths[x][y] == lengths[x][y-1] )
+					y--;
+				else {
+					res +=a.charAt(x-1);
+					x--;
+					y--;
+				}
+			}
+			return res.split("").reverse().join("");
+		}
+
+	    
+	    static public function lcslen( a:String, b:String) :int {
+	    	return lcs(a,b).length;
+	    } 
+	    
+	    static public function commonCharacterPositions( a:String, b:String, refObj:RefObject):int {
+			var num:int = 0, i:int;
+			var diff:int = 0;
+			var diffpos:Array = new Array(2);
+			refObj.ref  = 0;
+	    	b = b.toLocaleLowerCase();
+	    	for ( i =0; (i < a.length) && ( i<b.length); ++i ) {
+	    		if ( a.charAt(i) == b.charAt(i) ) {
+	    			num++;
+	    		}else {
+	    			if ( diff < 2) diffpos[diff] = i;
+	    			diff++;
+	    		}
+	    	}
+	    	if ( (diff == 2) && ( i=(a.length-1) ) && ( i==(b.length-1)) && (a.charCodeAt(diffpos[0]) == b.charCodeAt(diffpos[1])) && ( a.charCodeAt( diffpos[1]) == b.charCodeAt(diffpos[0]) ))
+	    		refObj.ref = 1;
+	    	
+	    	return num;
+	    }
+	    
+		/*
+		* To find if the Numbers are present in the word
+		* 
+		* returns true if hasNumber else returns false
+		*/
+		public static function getHasNumber(word:String):Boolean {
+			var i:int;
+			for ( i=0 ; i < word.length ; ++i ) {
+				if ( (word.charCodeAt(i) <= 57 ) && ( word.charCodeAt(i) >= 48) ) { // '0' to '9'
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+}
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SuggestionsResult.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SuggestionsResult.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SuggestionsResult.as
new file mode 100644
index 0000000..8a43921
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/SuggestionsResult.as
@@ -0,0 +1,142 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	public class SuggestionsResult
+	{
+		private var _myHeap:Array;
+		private var _count:uint=0;
+		private var _size:uint=1;
+		private var __compare:Function;
+		public function SuggestionsResult(buffersize:uint=100, compare:Function = null)
+		{
+			_size=buffersize;
+			_myHeap= new Array(_size+1);
+			_count=0;
+			if (compare == null)
+				__compare = function(a:int, b:int):int { return a - b; };
+			else
+				__compare = compare;
+		}
+		public function insert(obj:*):Boolean {
+			_myHeap[++_count]=obj;
+			return true;
+		}
+		public function find(obj:*):Boolean {
+			for (var i:int = 1; i <= _count; i++)
+			{
+				if (_myHeap[i] === obj)
+					return true;
+			}
+			return false;
+		}
+
+		public function get front():*
+		{
+			return this._myHeap[1];
+		}
+
+		public function get maxSize():int
+		{
+			return this._size;
+		}
+
+		public function isEmpty():Boolean
+		{
+			if (_count==0) {
+				return true;
+			}else {
+				return false;
+			}
+			
+		}
+		
+		public function clear():void
+		{
+			_myHeap = new Array(_size);
+			_count = 0;
+		}
+		
+		public function get size():uint {
+			return this._count;
+		}
+		
+		public function dump():String {
+			var s:String = "Suggestions Result\n{\n";
+			var k:int = _count + 1;
+			for (var i:int = 1; i < k; i++)
+				s += "\t" + _myHeap[i] + "\n";
+			s += "\n}";
+			return s;
+		}
+		
+		public function toArray():Array {
+			return _myHeap.slice(1,_count+1);
+		}
+		
+		
+		public function get data():Array {
+			return this._myHeap;
+		}
+		
+		public function buildheap():void {
+			if(this.size<2) {
+				return;
+			}
+			for ( var i:int=this.size/2;i>0;i--) {
+				minheapify(i);
+			}
+		}
+		
+		public function updateFront():void {
+			minheapify(1);
+		}
+		
+		private function minheapify(index:uint):void {
+			var i:int = index;
+			var child:int = i << 1;
+			var tmp:* = _myHeap[i];
+			var v:*;
+			
+			while (child <= _count)
+			{
+				if (child < _count - 1)
+				{
+					if (__compare(_myHeap[child], _myHeap[int(child + 1)]) > 0)
+						child++;
+				}
+				v = _myHeap[child];
+				if (__compare(tmp, v) > 0)
+				{
+					_myHeap[i] = v;
+					i = child;
+					child <<= 1;
+				}
+				else break;
+			}
+			_myHeap[i] = tmp;
+
+		}	
+		
+	}
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Token.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Token.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Token.as
new file mode 100644
index 0000000..52e2c8a
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Token.as
@@ -0,0 +1,47 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	public class Token
+	{
+		private var _first:uint;
+		private var _last:uint;
+		
+		public function Token(inFirst:uint, inLast:uint)
+		{
+			_first = inFirst;
+			_last = inLast;
+		}
+		
+		public function get first():uint
+		{
+			return _first;
+		}
+		
+		public function get last():uint
+		{
+			return _last;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Tokenizer.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Tokenizer.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Tokenizer.as
new file mode 100644
index 0000000..6ccbd8a
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/Tokenizer.as
@@ -0,0 +1,96 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+
+	import com.adobe.linguistics.spelling.utils.Token;
+		
+	public class Tokenizer
+	{
+		private var _data:String;
+		private var _current:uint;
+
+		public function Tokenizer(inText:String)
+		{
+			_data = inText;
+			_current = 0;
+		}
+		public function next():Token
+		{
+			var first:uint;
+			var last:uint;
+			
+			if (_current==_data.length) return null;
+			while (isSeparator(_data.charAt(_current))) {
+				_current++;
+				if (_current==_data.length) return null;
+			}
+			first = _current;
+			while (!isSeparator(_data.charAt(_current))) {
+				_current++;
+				if (_current==_data.length) break;
+			}
+			last = _current;
+			
+			// Special handling for single quote
+			var charFirst:Number = _data.charCodeAt(first);
+			var charLast:Number = _data.charCodeAt(last-1);
+			if ((charFirst == 39) || (charFirst == 0x2018) || (charFirst == 0x2019)) first++;
+			if ((charLast == 39) || (charLast == 0x2018) || (charLast == 0x2019)) last--;
+			
+			return new Token(first, last);	
+		}
+		
+		private static var allValidChars:Array = [
+			{startingChar:65, endingChar:90}, /*Basic Latin bof */
+			{startingChar:97, endingChar:122},/*Basic Latin eof */
+			{startingChar:39, endingChar:39}, /* "'" character*/
+			{startingChar:0x2018, endingChar:0x2019}, /* "‘" and "’" character*/
+			{startingChar:192, endingChar:214},/* Latin-1 supplement  bof */
+			{startingChar:216, endingChar:246},
+			{startingChar:248, endingChar:255},/* Latin-1 supplement  eof */
+			{startingChar:256, endingChar:383},/* Lating Extended-A bof-eof    European Latin*/
+			{startingChar:384, endingChar:447}, /* Latin extended-B bof-eof */
+			{startingChar:48, endingChar:57}, /* number */
+			{startingChar:536, endingChar:537} /* "ş" character, for romanian */
+		];
+		private static function isValidCharacter( inChar:int ) :Boolean {
+			for ( var i:int = 0; i < allValidChars.length; ++i ) {
+				if ( (inChar >= allValidChars[i].startingChar) && (inChar <= allValidChars[i].endingChar) )
+					return true; 
+			}
+			return false;
+		} 
+		
+		public static function isSeparator(inChar:String):Boolean
+		{	
+			var ccode:Number = inChar.charCodeAt();
+			if ( isValidCharacter( ccode ) )
+				return false;
+			return true;
+		}
+
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
new file mode 100644
index 0000000..358036b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
@@ -0,0 +1,120 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	[RemoteClass]
+	public class WordList
+	{
+		private var _words:Array;
+		private var _sorted:Boolean;  // TODO: Shouldn't be always sorted?
+
+		public function WordList(wordsList:Array=null)
+		{
+			if(wordsList!=null) {
+				_words=wordsList;	
+			}else {
+				_words=new Array();
+			}
+			
+		}
+		
+		public function toArray():Array {
+			return this._words;
+		}
+
+		public function set data(inData:Array):void {
+			this._words = inData;
+		}
+		
+		public function get data():Array {
+			return this._words;
+		}
+		
+		public function insert(value:String):Boolean {
+			if( _words.length==0 ) {
+				_words.push(value)
+				return true;
+			}
+			var low:uint= 0;
+			var high:uint= _words.length-1;
+			var middle:uint= (low+high)/2;
+			while (low<high) {
+				if(_words[middle]<value) {
+					low=middle+1;
+				}else {
+					high=middle;
+				}
+				middle= (low+high)/2;
+			}
+			if( (low <= _words.length-1) && (_words[low]!=value) ) {
+				var pos:uint=_words[low]>value?low:low+1;
+				_words.splice(pos,0,value);
+				return true;
+			}else {
+				return false;
+			}
+			_words.push(value);
+			return true;
+		}
+		
+		public function remove(value:String):Boolean {
+			var pos:int= lookup(value);
+			if( pos!= -1 ) {
+				_words.splice(pos,1);
+				return true;
+			}else {
+				return false;
+			}
+		}
+		
+		//binary search to find the word.
+		public function lookup(value:String):int {
+			if(_words.length==0) {
+				return -1;
+			}
+			var low:uint= 0;
+			var high:uint= _words.length-1;
+			var middle:uint= (low+high)/2;
+			while (low<high) {
+				if(_words[middle]<value) {
+					low=middle+1;
+				}else {
+					high=middle;
+				}
+				middle= (low+high)/2;
+			}
+			if( (low <= _words.length-1) && (_words[low]==value) ) {
+				return low;
+			}else {
+				return -1;
+			}
+			
+		}
+		
+		public function mergeWordLists(list1:WordList,list2:WordList):WordList {
+			return null;
+		}
+
+	}
+}
\ No newline at end of file


[03/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as
new file mode 100644
index 0000000..9ea0f9a
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SquigglyCustomContainerController.as
@@ -0,0 +1,258 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.SpellUIForTLF;
+	import com.adobe.linguistics.spelling.framework.SpellingService;
+	import com.adobe.linguistics.spelling.ui.IHighlighter;
+	import com.adobe.linguistics.spelling.ui.IWordProcessor;
+	import com.adobe.linguistics.spelling.ui.TLFHighlighter;
+	import com.adobe.linguistics.spelling.ui.TLFWordProcessor;
+	import com.adobe.linguistics.utils.TextTokenizer;
+	import com.adobe.linguistics.utils.Token;
+	
+	import flash.display.Sprite;
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.ui.ContextMenu;
+	import flash.ui.ContextMenuItem;
+	
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.textLayout.tlf_internal;
+	
+	/** Custom container controller for populating context menu and hanlding menu item selection  */
+	internal class SquigglyCustomContainerController extends ContainerController
+	{
+		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 mTextFlow:TextFlow;
+		private var _ignoreWordFunctionProcessor:Function;
+		private var _misspelledToken:Token;
+		private var _misspelled:String;
+		
+		public function SquigglyCustomContainerController(container:Sprite,textHighlighter:IHighlighter, wordProcessor:IWordProcessor, engine:SpellingService,
+														  func:Function, compositionWidth:Number=100,compositionHeight:Number=100)
+		{
+			super (container, compositionWidth, compositionHeight);
+			mTextHighlighter = textHighlighter;
+			mWordProcessor = wordProcessor;
+			mSpellEngine = engine;
+			_ignoreWordFunctionProcessor = func;
+			
+			spellingEnabled = true;
+		}
+		
+		/** Overridden to add custom items to the context menu */
+		override protected function createContextMenu():ContextMenu
+		{
+			// Get the default context menu used by TLF for editable flows
+			_contextMenu = super.container.contextMenu;
+			if (_contextMenu == null)
+				_contextMenu = super.createContextMenu();
+				
+			
+			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);
+			
+			// Listen for menu selection
+			_contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, updateCustomMenuItems);
+			
+			return _contextMenu;
+		}
+		
+		/** Update the state of the custom menu items before the context menu is displayed */
+		private function updateCustomMenuItems(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 = SpellUIForTLF.getSpellingMenuEntries();
+			disableMenuItem.caption = entries.disable;
+			enableMenuItem.caption = entries.enable;				
+			
+			if (spellingEnabled == true) {
+				(mWordProcessor as TLFWordProcessor).textFlowContainerController = this;
+				
+				//trace("stageX " +  super.container.stage.mouseX);
+				//trace("stageY " +  super.container.stage.mouseY);
+				//trace("mouseX " +  super.container.mouseX);
+				//trace("mouseY " +  super.container.mouseY);
+				_misspelledToken = mWordProcessor.getWordAtPoint(this.container.mouseX, this.container.mouseY);
+				if (_misspelledToken==null) return;
+				var currentLeaf:FlowLeafElement = this.textFlow.findLeaf(_misspelledToken.first);
+				var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null;
+				_misspelled = 	currentParagraph.getText().substring(_misspelledToken.first - currentParagraph.getAbsoluteStart(), 
+																		_misspelledToken.last - currentParagraph.getAbsoluteStart());
+				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);
+					}
+				}
+			}
+		}
+		
+		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);
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[super.textFlow]].doSpellingJob();
+		}
+		
+		private function handleSuseItemSelect(event:ContextMenuEvent):void
+		{
+			mWordProcessor.replaceText(_misspelledToken, (event.currentTarget as ContextMenuItem).caption );
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[super.textFlow]].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 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 handleEnableSpellCheck(event:ContextMenuEvent):void
+		{
+			spellingEnabled= true;
+			//mTextHighlighter.spellingEnabled= spellingEnabled;
+			//SpellUI.doSpellingJob();
+			//dispatchEvent(new Event(Event.RENDER));
+			
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].spellingEnabled = spellingEnabled;
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].doSpellingJob();
+			//spellCheckRange(getValidFirstWordIndex(), getValidLastWordIndex());
+		}
+		private function handleDisableSpellCheck(event:ContextMenuEvent):void
+		{
+			spellingEnabled= false;
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[this.textFlow]].spellingEnabled = spellingEnabled;
+			mTextHighlighter.clearSquiggles();
+		}
+		
+		public function cleanUpContextMenu():void
+		{
+			mTextHighlighter=null;
+			mWordProcessor=null;
+			spellingEnabled = false;
+			_ignoreWordFunctionProcessor=null;
+			
+			_contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, updateCustomMenuItems);
+			
+			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;
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Automation/asdocgen.bat
----------------------------------------------------------------------
diff --git a/Squiggly/main/Automation/asdocgen.bat b/Squiggly/main/Automation/asdocgen.bat
new file mode 100644
index 0000000..c9f3925
--- /dev/null
+++ b/Squiggly/main/Automation/asdocgen.bat
@@ -0,0 +1,18 @@
+@echo off
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements.  See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License.  You may obtain a copy of the License at
+rem
+rem     http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+REM This generates the ASDoc for Engine and SInC. Modify the path as you need.
+"C:\flexsdk4.1\bin\asdoc" -source-path ..\AdobeSpellingUI\src ..\AdobeSpellingUITLF\src ..\AdobeSpellingEngine\src ..\AdobeLinguisticUtils\src ..\AdobeSpellingFramework\src -doc-classes com.adobe.linguistics.spelling.SpellUI com.adobe.linguistics.spelling.SpellUIForTLF com.adobe.linguistics.spelling.HunspellDictionary com.adobe.linguistics.spelling.SpellChecker com.adobe.linguistics.spelling.UserDictionary com.adobe.linguistics.utils.TextTokenizer com.adobe.linguistics.utils.Token com.adobe.linguistics.spelling.framework.ResourceTable com.adobe.linguistics.spelling.framework.SpellingConfiguration com.adobe.linguistics.spelling.framework.SpellingService com.adobe.linguistics.spelling.ui.IHighlighter com.adobe.linguistics.spelling.ui.HaloHighlighter com.adobe.linguistics.spelling.ui.SparkHighlighter com.adobe.linguistics.spelling.ui.TLFHighlighter -library-path ..\AdobeSpellingEngine\bin  ..\AdobeLinguisticUtils\bin ..\AdobeSpellingUI\bin ..\AdobeSpellingUITLF\bin "C:\flexsdk4.1\frame
 works\libs" -exclude-dependencies=true -examples-path "..\ASDocExamples" -output Release\SquigglyDoc -main-title "Squiggly API Documentation 0.5" -package com.adobe.linguistics.spelling "This package providing spell checking functionality to your action script applications. This includes the core spell checking engine and the optional SpellUI class for easy integration with your existing Flex projects." -package com.adobe.linguistics.spelling.ui "This package provides text highlighting related functionalities" -package com.adobe.linguistics.spelling.framework "This package provides spelling service and spelling configuration related functionalities" -package com.adobe.linguistics.utils "This package provides text parsing and tokenizing related classes"

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Automation/copydictsandlibs.bat
----------------------------------------------------------------------
diff --git a/Squiggly/main/Automation/copydictsandlibs.bat b/Squiggly/main/Automation/copydictsandlibs.bat
new file mode 100644
index 0000000..7b55846
--- /dev/null
+++ b/Squiggly/main/Automation/copydictsandlibs.bat
@@ -0,0 +1,35 @@
+@echo off
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements.  See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License.  You may obtain a copy of the License at
+rem
+rem     http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+REM This copies dictionaries and libs to Release folder, do this after you build them in Flex builder 3/4
+mkdir Release
+mkdir Release\SquigglySDK
+mkdir Release\SquigglySDK\libs
+mkdir Release\SquigglySDK\src
+mkdir Release\SquigglySDK\src\dictionaries
+mkdir Release\SquigglySDK\src\dictionaries\en_US
+copy ..\AdobeSpellingEngine\bin\AdobeSpellingEngine.swc .\Release\SquigglySDK\libs
+copy ..\AdobeSpellingUI\bin\AdobeSpellingUI.swc .\Release\SquigglySDK\libs
+copy ..\AdobeSpellingUIEx\bin\AdobeSpellingUIEx.swc .\Release\SquigglySDK\libs
+copy ..\AdobeSpellingUITLF\bin\AdobeSpellingUITLF.swc .\Release\SquigglySDK\libs
+copy ..\AdobeSpellingFramework\bin\AdobeSpellingFramework.swc .\Release\SquigglySDK\libs
+copy ..\AdobeLinguisticUtils\bin\AdobeLinguisticUtils.swc .\Release\SquigglySDK\libs
+copy ..\..\releases\0.3\Dictionary\en_US.* .\Release\SquigglySDK\src\dictionaries\en_US
+copy ..\..\releases\0.3\Dictionary\*.txt .\Release\SquigglySDK\src\dictionaries\en_US
+copy ..\*.pdf .\Release\SquigglySDK\src\dictionaries\en_US
+copy ..\*.txt .\Release\SquigglySDK
+copy ..\..\releases\0.3\Dictionary\*.xml .\Release\SquigglySDK\src
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Automation/examplegen.py
----------------------------------------------------------------------
diff --git a/Squiggly/main/Automation/examplegen.py b/Squiggly/main/Automation/examplegen.py
new file mode 100644
index 0000000..0f9878a
--- /dev/null
+++ b/Squiggly/main/Automation/examplegen.py
@@ -0,0 +1,75 @@
+import shutil, os, stat, re, errno
+
+# 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.
+
+
+# Source and destination paths
+asdocExamplePath = "../ASDocExamples/com/adobe/linguistics/spelling/Examples"
+packageExamplePath = "./Release/SquigglySDK/Examples"
+
+# Go over all mxml files and modify them
+def modifyAll():
+    for root, dirs, files in os.walk(packageExamplePath):
+        for filename in files:
+            if '.mxml' in filename:
+                modifyMxml(os.path.join(root, filename))
+                
+# Modify one mxml file by removing all asdoc comments
+def modifyMxml(filename):
+    print filename + "....."
+    code = file(filename, 'r').read()
+    code = removeComment(code)
+    if (not os.stat(filename)[0] & stat.S_IWRITE):
+        os.chmod(filename, stat.S_IWRITE)
+    file(filename, 'w').write(code)
+
+# Remove asdoc comment, we don't remove // comment
+def removeComment(text):
+    def replacer(match):
+        s = match.group(0)
+        if s.startswith('/'):
+            return ""
+        else:
+            return s
+    pattern = re.compile(
+        r'/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
+        re.DOTALL | re.MULTILINE
+    )
+    return re.sub(pattern, replacer, text)
+
+# Remove a readonly file, required by windows
+def removeReadonly(func, path, exc):
+  excvalue = exc[1]
+  if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
+      os.chmod(path, stat.S_IWRITE)
+      func(path)
+  else:
+      raise
+
+# Main function
+def main():
+    print "Removing the asdoc comments from mxml source code"
+    if os.path.isdir(packageExamplePath):
+        shutil.rmtree(packageExamplePath, onerror=removeReadonly)
+    shutil.copytree(asdocExamplePath, packageExamplePath)
+    modifyAll()
+    print "Done! Check " + packageExamplePath + " for example code."
+
+if __name__ == '__main__':
+    main()
+        
+    
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Automation/prepareReleasePackage.bat
----------------------------------------------------------------------
diff --git a/Squiggly/main/Automation/prepareReleasePackage.bat b/Squiggly/main/Automation/prepareReleasePackage.bat
new file mode 100644
index 0000000..0cc9174
--- /dev/null
+++ b/Squiggly/main/Automation/prepareReleasePackage.bat
@@ -0,0 +1,20 @@
+@echo off
+rem Licensed to the Apache Software Foundation (ASF) under one or more
+rem contributor license agreements.  See the NOTICE file distributed with
+rem this work for additional information regarding copyright ownership.
+rem The ASF licenses this file to You under the Apache License, Version 2.0
+rem (the "License"); you may not use this file except in compliance with
+rem the License.  You may obtain a copy of the License at
+rem
+rem     http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing, software
+rem distributed under the License is distributed on an "AS IS" BASIS,
+rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+rem See the License for the specific language governing permissions and
+rem limitations under the License.
+
+REM This prepare the Release folder, do this after you build them in Flex builder 3/4
+call copydictsandlibs.bat
+python examplegen.py
+call asdocgen.bat

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Data/genTextWordlist.sh
----------------------------------------------------------------------
diff --git a/Squiggly/main/Data/genTextWordlist.sh b/Squiggly/main/Data/genTextWordlist.sh
new file mode 100644
index 0000000..d4e31e5
--- /dev/null
+++ b/Squiggly/main/Data/genTextWordlist.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+# 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.
+
+
+
+
+
+# Author (U)  Zhigang Qi (zhigang.qi@gmail.com) XieFang (xfang@adobe.com)
+# Created  02/26/2010
+
+
+# Put your selected word lists in squigglyWordlist folder, then run this #
+
+
+cat squigglyWordlist/* | sort > usatemp.txt
+uniq usatemp.txt usa.txt
+rm -f usatemp.txt


[10/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/LinguisticRule.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/LinguisticRule.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/LinguisticRule.as
new file mode 100644
index 0000000..6ad78c6
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/LinguisticRule.as
@@ -0,0 +1,1118 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+//	import com.adobe.linguistics.spelling.core.PhoneticTable;
+	import com.adobe.linguistics.spelling.core.env.*;
+	import com.adobe.linguistics.spelling.core.error.*;
+	import com.adobe.linguistics.spelling.core.rule.*;
+	import com.adobe.linguistics.spelling.core.utils.SimpleNumberParser;
+	
+	import flash.utils.Dictionary;
+
+
+	public class LinguisticRule
+	{
+
+
+		private var _encoding:String // ToDo, not sure how to handle this encoding stuff...
+
+		private var snp:SimpleNumberParser = new SimpleNumberParser();
+		
+		private var _prefixFlagTable:Array;
+		private var _prefixKeyTable:Array;
+		private var _suffixFlagTable:Array;
+		private var _suffixKeyTable:Array;
+		private var _optSuffixKeyTable:Dictionary;
+		private var _optPrefixKeyTable:Dictionary;
+//these are attributes
+		private var _keyString:String;
+		private var _tryString:String;
+		private var _noSuggest:Number;// don't suggest words signed with NOSUGGEST flag
+		private var _forbiddenWord:Number; // forbidden word signing flag
+		private var _circumfix:Number=0; //Circumfix Flag
+		private var _ignoredChars:String; // letters + spec. word characters
+		private var _wordChars:String; //extends tokenizer of Hunspell command line interface with additional word character. For example, dot, dash, n-dash, numbers, percent sign are word character in Hungarian.
+		private var _languageCode:String; 
+		private var _version:String;
+		private var _maxngramsugs:int = -1; // undefined
+		private var _nosplitsugs:int = 0;
+		private var _sugswithdots:int = 0;
+		private var _fullStrip:int;
+		private var _keepCase:Number;
+		private var _haveContClass:Boolean;//added to support (double) prefixes
+		
+		private var _flagMode:int;
+		private var _needAffix:Number;
+		private var _contClasses:Dictionary;//this is list of all possible contclasses
+		/* ToDo */
+		
+		private var _onlyInCompound:Number = 0;
+//		private var _phoneTable:PhoneticTable; //phone table
+/*
+
+
+ToDO: should be removed after we have complex-affix support and compound-word support..
+
+
+  pHMgr = ptr[0];
+  alldic = ptr;
+  maxdic = md;
+  keystring = NULL;
+  trystring = NULL;
+  encoding=NULL;
+  utf8 = 0;
+  complexprefixes = 0;
+  maptable = NULL;
+  nummap = 0;
+  breaktable = NULL;
+  numbreak = 0;
+  reptable = NULL;
+  numrep = 0;
+  iconvtable = NULL;
+  oconvtable = NULL;
+  checkcpdtable = NULL;
+  // allow simplified compound forms (see 3rd field of CHECKCOMPOUNDPATTERN)
+  simplifiedcpd = 0;
+  numcheckcpd = 0;
+  defcpdtable = NULL;
+  numdefcpd = 0;
+  phone = NULL;
+  compoundflag = FLAG_NULL; // permits word in compound forms
+  compoundbegin = FLAG_NULL; // may be first word in compound forms
+  compoundmiddle = FLAG_NULL; // may be middle word in compound forms
+  compoundend = FLAG_NULL; // may be last word in compound forms
+  compoundroot = FLAG_NULL; // compound word signing flag
+  compoundpermitflag = FLAG_NULL; // compound permitting flag for suffixed word
+  compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word
+  checkcompounddup = 0; // forbid double words in compounds
+  checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution)
+  checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds
+  checkcompoundtriple = 0; // forbid compounds with triple letters
+  simplifiedtriple = 0; // allow simplified triple letters in compounds (Schiff+fahrt -> Schiffahrt)
+  forbiddenword = FORBIDDENWORD; // forbidden word signing flag
+  nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag
+  lang = NULL; // language
+  langnum = 0; // language code (see http://l10n.openoffice.org/languages.html)
+  needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes
+  cpdwordmax = -1; // default: unlimited wordcount in compound words
+  cpdmin = -1;  // undefined
+  cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words
+  cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX)
+  cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search)
+  cpdvowels_utf16_len=0; // vowels
+  pfxappnd=NULL; // previous prefix for counting the syllables of prefix BUG
+  sfxappnd=NULL; // previous suffix for counting a special syllables BUG
+  cpdsyllablenum=NULL; // syllable count incrementing flag
+  checknum=0; // checking numbers, and word with numbers
+  wordchars=NULL; // letters + spec. word characters
+  wordchars_utf16=NULL; // letters + spec. word characters
+  wordchars_utf16_len=0; // letters + spec. word characters
+  ignorechars=NULL; // letters + spec. word characters
+  ignorechars_utf16=NULL; // letters + spec. word characters
+  ignorechars_utf16_len=0; // letters + spec. word characters
+  version=NULL; // affix and dictionary file version string
+  havecontclass=0; // flags of possible continuing classes (double affix)
+  // LEMMA_PRESENT: not put root into the morphological output. Lemma presents
+  // in morhological description in dictionary file. It's often combined with PSEUDOROOT.
+  lemma_present = FLAG_NULL; 
+  circumfix = FLAG_NULL; 
+  onlyincompound = FLAG_NULL; 
+  maxngramsugs = -1; // undefined
+  nosplitsugs = 0;
+  sugswithdots = 0;
+  keepcase = 0;
+  checksharps = 0;
+  substandard = FLAG_NULL;
+  fullstrip = 0;
+  */
+		
+		private var _simpleFilterTable:Array;
+		private var _mapFilterTable:Array;
+		private var _iconvFilterTable:Array; //Contains conversion table for ICONV conversion
+		private var _oconvFilterTable:Array;//Contains conversion table for OCONV conversion
+		private var _breakTable:Array;//Contains list of characters in BREAK rule
+		private var _aliasfTable:Array;//Contains conversion table for AF rule
+		/* internal use only properties. */
+		private var _pfxEntry:PrefixEntry;
+		private var _sfxEntry:SuffixEntry;
+		private var _optSfxEntry:OptimizedSuffixEntry;
+		private var _optPfxEntry:OptimizedPrefixEntry;
+		private var _dictMgr:DictionaryManager;
+		
+		public function LinguisticRule()
+		{
+			
+			this._prefixFlagTable = new Array()
+			this._prefixKeyTable = new Array();
+			this._suffixFlagTable = new Array();
+			this._suffixKeyTable = new Array();
+			this._optSuffixKeyTable = new Dictionary(true);
+			this._optPrefixKeyTable = new Dictionary(true);
+			
+			this._simpleFilterTable = new Array();
+			this._mapFilterTable = new Array();
+			this._iconvFilterTable=new Array();
+			this._oconvFilterTable=new Array();
+			this._breakTable=new Array();//We are not adding any break points by default. Hunspell C does this for -, ^-, -$
+			this._aliasfTable=new Array();
+//			this._phoneTable=new PhoneticTable(); 
+			
+			
+			/* init the attributes */
+			this.noSuggest = InternalConstants.FLAG_NULL;
+			this.tryString= null;
+			this.keyString= null;
+			this.ignoredChars = null;
+			this.wordChars = null;
+			this.version = null;
+			this.languageCode = null;
+			this.forbiddenWord = InternalConstants.FORBIDDENWORD;
+			this.needAffix=InternalConstants.FLAG_NULL;
+			this.circumfix=InternalConstants.FLAG_NULL;
+			this.maxNgramSuggestions = -1; // undefined
+			this.nosplitSuggestions = 0;
+			this.suggestionsWithDots = 0;
+			this.fullStrip = 0;
+			this.keepCase = 0;
+			this.onlyInCompound = 0;
+			this.flagMode = InternalConstants.FLAG_CHAR;
+			this._contClasses= new Dictionary;
+			/* */
+			
+			
+			this._dictMgr = null;
+			
+
+		}
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		// check if word with affixes is correctly spelled
+		public function affixCheck( word:String, needFlag:int, inCompound:int ):HashEntry {
+			var rv:HashEntry = null;
+			// check all prefixes (also crossed with suffixes if allowed) 
+			rv = optSuffixCheck(word, needFlag, inCompound);
+			if( rv ) return rv;
+			// if still not found check all suffixes
+			rv = optPrefixCheck(word, 0, null, inCompound, needFlag);
+			return rv;
+		}
+
+		// This function checks if word with affixes is correctly spelled.
+		public function affixCheck2( word:String, needFlag:int, inCompound:int ):HashEntry {
+			var rv:HashEntry = null;
+			if ( word.length <2 ) return rv;
+			// check onelevel prefix case or one level prefix+one level suffix: un->run or under->taker (note: hypothetical words) also will check milli->litre->s and d'->autre->s
+			rv = optPrefixCheck2(word, inCompound, needFlag);
+			if( rv ) return rv;
+			// check all one level suffix drink->able or drink->s
+			rv = optSuffixCheck2(word,0,null, needFlag, inCompound);
+			
+			
+			//double affix checking 
+			if(this.haveContClass)
+			{
+				if(rv) return rv;
+				//check all 2 level suffixes case: drink->able->s
+				rv= optTwoSuffixCheck(word,0, null, needFlag,0);
+				
+				if(rv) return rv;
+				//check prefix and then 2 level suffix case un->drink->able->s
+				rv= optTwoPrefixCheck(word, 0, needFlag);
+				
+			}
+				
+				return rv;
+		}
+
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		public function optPrefixCheck(word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int) :HashEntry {
+			var rv:HashEntry = null;
+			var tmpWord:String;
+			// first handle the special case of 0 length prefixes
+			if ( _optPrefixKeyTable[''] != undefined ) {
+				_optPfxEntry = _optPrefixKeyTable[''];
+				while ( _optPfxEntry ) {
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					rv = _optPfxEntry.checkWord(word, sfxopts, ppfx, inCompound, needFlag);
+					if ( rv ) {
+						return rv;
+					}
+					_optPfxEntry = _optPfxEntry.nextElementWithKey;
+				}
+			}
+			
+			// now handle the general case
+			for ( var i:int =1; i < word.length ; ++i ) {
+				tmpWord = word.substr(0,i);
+				if ( _optPrefixKeyTable[tmpWord] != undefined ) {
+					_optPfxEntry = _optPrefixKeyTable[tmpWord];
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( _optPfxEntry ) {
+						rv = _optPfxEntry.checkWord(word, sfxopts, ppfx, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						_optPfxEntry = _optPfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+
+// This function checks one level prefix OR one level prefix+ one level suffix
+		public function optPrefixCheck2(word:String, inCompound:int, needFlag:int) :HashEntry {
+			var rv:HashEntry = null;
+			var tmpWord:String;
+			var i:int;
+			var locOptPfxEntry:OptimizedPrefixEntry=null;//local optimised prefix entry added because we are adding optTwoPrefixCheck
+			// first handle the special case of 0 length prefixes
+			if ( _optPrefixKeyTable[''] != undefined ) {
+				for ( i=0; i<_optPrefixKeyTable[''].length; ++i ) {
+					locOptPfxEntry=_optPrefixKeyTable[''][i];
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( locOptPfxEntry ) {
+						rv = locOptPfxEntry.checkWord2(word, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						locOptPfxEntry = locOptPfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			// now handle the general case
+			var firstKeyStr:String = word.charAt(0);
+			var secondKeyNum:Number = word.charCodeAt(1);
+			var breakFlag:Boolean = false;
+			if ( _optPrefixKeyTable[firstKeyStr] != undefined ) {
+				for ( i=0; i< _optPrefixKeyTable[firstKeyStr].length; ++i ) {
+					locOptPfxEntry=_optPrefixKeyTable[firstKeyStr][i];
+					if ( (locOptPfxEntry.affixKey.length!=1) ) {
+						if ( locOptPfxEntry.affixKey.charCodeAt(1)> secondKeyNum )
+							break;
+						if ( locOptPfxEntry.affixKey.charCodeAt(1)< secondKeyNum) {
+							if (breakFlag) break;
+							else continue;
+						}
+						breakFlag = true;
+					}
+					if (word.indexOf(locOptPfxEntry.affixKey) != 0)
+						continue; 
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( locOptPfxEntry ) {
+						rv = locOptPfxEntry.checkWord2(word, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						locOptPfxEntry = locOptPfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+
+		// This is a new function added to include one level prefix checking followed by two level suffix checking
+		public function optTwoPrefixCheck(word:String, inCompound:int, needFlag:int) :HashEntry {
+			var rv:HashEntry = null;
+			//pfx=null;//TODO:Need to figure these out, seems they will be needed for compound rules. keeping for some time
+			//sfxrevkey=null;//TODO:Need to figure these out, seems they will be needed for compound rules. keeping for some time
+			var tmpWord:String;
+			var i:int;
+			var locOptPfxEntry:OptimizedPrefixEntry=null;//local optimised prefix entry
+			// first handle the special case of 0 length prefixes
+			if ( _optPrefixKeyTable[''] != undefined ) {
+				for ( i=0; i<_optPrefixKeyTable[''].length; ++i ) {
+					locOptPfxEntry=_optPrefixKeyTable[''][i];
+					
+					while ( locOptPfxEntry ) {
+						rv = locOptPfxEntry.checkTwoWord(word, inCompound, needFlag); 
+						if ( rv) {
+							return rv;
+						}
+						locOptPfxEntry = locOptPfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			// now handle the general case
+			var firstKeyStr:String = word.charAt(0);
+			var secondKeyNum:Number = word.charCodeAt(1);
+			var breakFlag:Boolean = false;
+			if ( _optPrefixKeyTable[firstKeyStr] != undefined ) {
+				for ( i=0; i< _optPrefixKeyTable[firstKeyStr].length; ++i ) {
+					locOptPfxEntry=_optPrefixKeyTable[firstKeyStr][i];
+					if ( (locOptPfxEntry.affixKey.length!=1) ) {
+						if ( locOptPfxEntry.affixKey.charCodeAt(1)> secondKeyNum )
+							break;
+						if ( locOptPfxEntry.affixKey.charCodeAt(1)< secondKeyNum) {
+							if (breakFlag) break;
+							else continue;
+						}
+						breakFlag = true;
+					}
+					if (word.indexOf(locOptPfxEntry.affixKey) != 0)
+						continue; 
+					while ( locOptPfxEntry ) {
+						rv = locOptPfxEntry.checkTwoWord(word, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						locOptPfxEntry = locOptPfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			return rv;//this most certainly will return NULL
+		}
+		
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		public function optSuffixCheck( word:String, needFlag:int, inCompound:int):HashEntry {
+			var rv:HashEntry  = null;
+			var tmpWord:String;
+			// first handle the special case of 0 length suffixes
+			if ( this._optSuffixKeyTable[''] != undefined  ) {
+				_optSfxEntry = this._optSuffixKeyTable[''];
+				while ( _optSfxEntry ) {
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					rv = _optSfxEntry.checkWord(word, inCompound, needFlag);
+					if ( rv ) {
+						return rv;
+					}
+					_optSfxEntry = _optSfxEntry.nextElementWithKey;
+				}
+				
+			}
+			// now handle the general case
+			for ( var i:int =word.length-1; i > 0 ; --i ) {
+				tmpWord = word.substr(i);
+				if ( _optSuffixKeyTable[tmpWord] != undefined ) {
+					_optSfxEntry = _optSuffixKeyTable[tmpWord];
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( _optSfxEntry ) {
+						rv = _optSfxEntry.checkWord(word, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						_optSfxEntry = _optSfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+
+//This function takes care of all one level suffix stripping. This is called from other affix stripping functions also
+		public function optSuffixCheck2( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int, cclass:int=0, pfxcclass:int=0):HashEntry {
+			var rv:HashEntry  = null;
+			var tmpWord:String;
+			var locOptSfxEntry:OptimizedSuffixEntry=null;//local optimised suffic entry
+			// first handle the special case of 0 length suffixes
+			if ( this._optSuffixKeyTable[''] != undefined  ) {
+				locOptSfxEntry=this._optSuffixKeyTable[''];
+				while ( locOptSfxEntry ) {
+					//if(!cclass|| locOptSfxEntry.contclass)
+					//{
+						
+					
+					
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+						
+					//if((_optSfxEntry &&!(_optSfxEntry.contclass && HashEntry.TESTAFF(_optSfxEntry.contclass, this._needAffix)))||(ppfx&& !(ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._needAffix))))// needaffix on prefix or first suffix
+					//{
+						
+						rv = locOptSfxEntry.checkWord2(word, sfxopts, ppfx, inCompound, needFlag, cclass, pfxcclass);
+						if ( rv ) {
+							_optSfxEntry = locOptSfxEntry;//WIll possibily needed in compound check
+							return rv;
+						}
+				//	}
+					//}
+					locOptSfxEntry = locOptSfxEntry.nextElementWithKey;
+				}
+				
+			}
+			// now handle the general case
+			for ( var i:int =word.length-1; i >= 0 ; --i ) {
+				tmpWord = word.substr(i);
+				if ( _optSuffixKeyTable[tmpWord] != undefined ) {
+					locOptSfxEntry = (_optSuffixKeyTable[tmpWord] is OptimizedSuffixEntry)? _optSuffixKeyTable[tmpWord] : null;
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( locOptSfxEntry ) {
+						//if(_optSfxEntry &&HashEntry.TESTAFF(_optSfxEntry.contclass, this._needAffix)||(ppfx&& HashEntry.TESTAFF(ppfx.contclass,this._needAffix)))// needaffix on prefix or first suffix
+						//{
+							
+							rv = locOptSfxEntry.checkWord2(word, sfxopts, ppfx, inCompound, needFlag, cclass, pfxcclass);
+							if ( rv) {
+								_optSfxEntry = locOptSfxEntry;//WIll possibily needed in compound check
+								return rv;
+							}
+						//}
+							locOptSfxEntry = locOptSfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+		
+		// This is a new function added to include two level suffix checking
+		public function optTwoSuffixCheck(word:String, sfxopts:int, ppfx:AffixEntry,needFlag:int,pfxcclass:int=0) :HashEntry {
+			var rv:HashEntry  = null;
+			var tmpWord:String;
+			var locOptSfxEntry:OptimizedSuffixEntry;//local optimised suffic entry
+			// first handle the special case of 0 length suffixes
+			if ( this._optSuffixKeyTable[''] != undefined  ) 
+			{
+				locOptSfxEntry=this._optSuffixKeyTable[''];
+				while ( locOptSfxEntry ) 
+				{
+					for(var j:int=0; locOptSfxEntry.flags && j<locOptSfxEntry.flags.length; j++)
+					{
+						if(this.contClasses[locOptSfxEntry.flags[j]]==true)
+						{ //if this can be a possible contclass check furthur
+							rv = locOptSfxEntry.checkTwoWord(word, sfxopts, ppfx, needFlag, locOptSfxEntry.flags[j], pfxcclass );
+							if (rv) 
+							{
+								_optSfxEntry = locOptSfxEntry;//WIll possibily needed in compound check
+								return rv;
+							}
+						
+						}
+					}
+					// get next suffix entry from table
+					locOptSfxEntry = locOptSfxEntry.nextElementWithKey;
+				}
+			}
+
+			//now handle the general case
+			for ( var i:int =word.length-1; i >= 0 ; --i ) 
+			{
+				tmpWord = word.substr(i);
+				if ( _optSuffixKeyTable[tmpWord] != undefined ) 
+				{
+					locOptSfxEntry = (_optSuffixKeyTable[tmpWord] is OptimizedSuffixEntry)? _optSuffixKeyTable[tmpWord] : null;
+					
+					while ( locOptSfxEntry )
+					{
+						for(j=0;locOptSfxEntry.flags && j<locOptSfxEntry.flags.length; j++)
+						{
+							if(this.contClasses[locOptSfxEntry.flags[j]]==true)
+							{	
+							 //if this can be a possible contclass check furthur
+							rv = locOptSfxEntry.checkTwoWord(word, sfxopts, ppfx, needFlag,locOptSfxEntry.flags[j], pfxcclass );
+							if ( rv) 
+								{
+								_optSfxEntry = locOptSfxEntry;//WIll possibily needed in compound check
+								return rv;	
+								}
+							}
+						}
+						locOptSfxEntry = locOptSfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;//will be null in most cases
+			
+		}
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		public function suffixCheck2( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int):HashEntry {
+			var rv:HashEntry  = null;
+			var tmpWord:String;
+			// first handle the special case of 0 length suffixes
+			if ( this._suffixKeyTable[''] != undefined  ) {
+				_sfxEntry = this._suffixKeyTable[''];
+				while ( _sfxEntry ) {
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					rv = _sfxEntry.checkWord(word, sfxopts, ppfx, inCompound, needFlag);
+					if ( rv ) {
+						return rv;
+					}
+					_sfxEntry = _sfxEntry.nextElementWithKey;
+				}
+				
+			}
+			// now handle the general case
+			for ( var i:int =word.length-1; i > 0 ; --i ) {
+				tmpWord = word.substr(i);
+				if ( _suffixKeyTable[tmpWord] != undefined ) {
+					_sfxEntry = _suffixKeyTable[tmpWord];
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( _sfxEntry ) {
+						rv = _sfxEntry.checkWord(word, sfxopts, ppfx, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						_sfxEntry = _sfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+
+		
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		private function prefixCheck2(word:String, inCompound:int, needFlag:int) :HashEntry {
+			var rv:HashEntry = null;
+			var tmpWord:String;
+			// first handle the special case of 0 length prefixes
+			if ( _prefixKeyTable[''] != undefined ) {
+				_pfxEntry = _prefixKeyTable[''];
+				while ( _pfxEntry ) {
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					rv = _pfxEntry.checkWord(word, inCompound, needFlag);
+					if ( rv ) {
+						return rv;
+					}
+					_pfxEntry = _pfxEntry.nextElementWithKey;
+				}
+			}
+			
+			// now handle the general case
+			for ( var i:int =1; i < word.length ; ++i ) {
+				tmpWord = word.substr(0,i);
+				if ( _prefixKeyTable[tmpWord] != undefined ) {
+					_pfxEntry = _prefixKeyTable[tmpWord];
+					// fogemorpheme
+					// permit prefixes in compounds
+						// check prefix
+					while ( _pfxEntry ) {
+						rv = _pfxEntry.checkWord(word, inCompound, needFlag);
+						if ( rv) {
+							return rv;
+						}
+						_pfxEntry = _pfxEntry.nextElementWithKey;
+					}
+				}
+			}
+			
+			return rv;
+		}
+		
+		public function lookup(word:String ):HashEntry {
+			var he:HashEntry = null;
+			var i:int;
+			// look word in hash table
+			for ( i=0; i < this._dictMgr.dictonaryList.length && !he; ++i ) {
+				he = this._dictMgr.dictonaryList[i].getElement(word);
+			}
+			return he;
+		}
+		
+		public function set flagMode(value:int) :void {
+			this._flagMode = value;
+		}
+		
+		public function get flagMode():int {
+			return this._flagMode;
+		}
+		
+		public function set encoding(value:String) :void {
+			this._encoding = value;
+		}
+		
+		public function get encoding():String {
+			return this._encoding;
+		}
+		
+		public function set keepCase(value:Number):void {
+			this._keepCase = value;
+		}
+		
+		public function get keepCase():Number {
+			return this._keepCase;
+		}
+		
+		public function set haveContClass(value:Boolean):void {
+			this._haveContClass = value;
+		}
+		
+		public function get haveContClass():Boolean {
+			return this._haveContClass;
+		}
+		
+		public function set needAffix(value:Number):void {
+			this._needAffix = value;
+		}
+		public function get needAffix():Number {
+			return this._needAffix;
+		}
+
+		
+		public function set circumfix(value:Number):void {
+			this._circumfix = value;
+		}
+		public function get circumfix():Number {
+			return this._circumfix;
+		}
+
+		public function set onlyInCompound(value:Number):void {
+			this._onlyInCompound = value;
+		}
+		public function get onlyInCompound():Number {
+			return this._onlyInCompound;
+		}
+
+		public function set dictionaryManager(value:DictionaryManager) :void {
+			this._dictMgr = value;
+		}
+		
+		public function get dictionaryManager():DictionaryManager {
+			return this._dictMgr;
+		}
+
+
+		public function set fullStrip(value:int):void {
+			this._fullStrip = value;
+		}
+		
+		public function get fullStrip():int {
+			return this._fullStrip;
+		}
+		
+		public function set suggestionsWithDots(value:int):void {
+			this._sugswithdots = value;
+		}
+		
+		public function get suggestionsWithDots():int {
+			return this._sugswithdots;
+		}
+		
+		public function set nosplitSuggestions(value:int ) :void {
+			this._nosplitsugs = value;
+		}
+		
+		public function get nosplitSuggestions():int {
+			return this._nosplitsugs;
+		}
+		
+		public function set maxNgramSuggestions(value:int ) :void {
+			this._maxngramsugs = value;
+		}
+		
+		public function get maxNgramSuggestions():int {
+			return this._maxngramsugs;
+		}
+		
+		public function set version(value:String) :void {
+			this._version = value;
+		}
+		
+		public function get version():String {
+			return this._version;
+		}
+		
+		public function set languageCode(value:String) :void {
+			this._languageCode = value;	
+		}
+		
+		public function get languageCode():String {
+			return this._languageCode;
+		}
+		
+		public function set wordChars(value:String):void {
+			this._wordChars= value;
+		}
+		
+		public function get wordChars():String {
+			return this._wordChars;
+		}
+
+		public function addMapFilter(mapString:String ):Boolean {
+			var mf:MapFilter = new MapFilter(mapString);
+			for ( var i:int; i< this._mapFilterTable.length; ++i ) {
+				if ( this._mapFilterTable[i].mapCharSet == mapString ) {
+					return false;
+				}
+			}
+			this._mapFilterTable.push(mf);
+			return true;
+		}
+
+		public function addSimpleFilter(matchString:String, replacement:String):Boolean {
+			var sf:SimpleFilter = new SimpleFilter( matchString, replacement);
+			for ( var i:int; i< this._simpleFilterTable.length; ++i ) {
+				if ( (this._simpleFilterTable[i].matchString==matchString) && (this._simpleFilterTable[i].replacement==replacement ) ) {
+					return false;
+				}
+			}
+			this._simpleFilterTable.push(sf);
+			return true;
+		}
+		
+	
+		//--adding to iconv/oconv table
+		
+		public function addConvFilter(matchString:String, replacement:String, ioflag:Boolean):Boolean {
+			var convTable:Array;
+			convTable=(ioflag==true)?this._iconvFilterTable:this._oconvFilterTable;
+			for ( var i:int; convTable && i< convTable.length; ++i ) {
+				if ( (convTable[i].matchString==matchString) && (convTable[i].replacement==replacement ) ) {
+					return false;
+				}
+			}
+			var sf:SimpleFilter = new SimpleFilter( matchString, replacement);
+			convTable.push(sf);
+			return true;
+		}
+		
+		public function addAffixEntry(affixFlag:int, stripString:String, affixValue:String, conditionsStr:String, morph:String = "", permission:Boolean = false, affixType:int = 0, contclass:String=null):Boolean{
+			if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+			if ( affixType == 0 ) {
+				if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+				var pfxEntry:PrefixEntry = new PrefixEntry(affixFlag,stripString,affixValue,conditionsStr,morph,permission,contclass);
+				pfxEntry.attributeManager = this;
+				addPrefixEntry(pfxEntry);
+				addOptPrefixEntry(pfxEntry);
+			}else {
+				if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+				var sfxEntry:SuffixEntry = new SuffixEntry(affixFlag,stripString,affixValue,conditionsStr,morph,permission,contclass);
+				sfxEntry.attributeManager = this;
+				addSuffixEntry(sfxEntry);	
+				addOptSuffixEntry(sfxEntry);
+			}
+			return true;
+		}
+
+		private function addOptPrefixEntry(pfxEntry:PrefixEntry):Boolean {
+			var optPfxEntry:OptimizedPrefixEntry
+			var hashKey:String = pfxEntry.affixKey.charAt(0);
+			optPfxEntry = new OptimizedPrefixEntry(pfxEntry);
+			optPfxEntry.attributeManager = this;
+			//insert prefix key table....
+			if ( _optPrefixKeyTable[hashKey] == undefined ) {
+				_optPrefixKeyTable[hashKey] = new Array();
+				_optPrefixKeyTable[hashKey].push(optPfxEntry);
+			}
+			else {
+				for each( var optPfxKeyEntry:OptimizedPrefixEntry  in _optPrefixKeyTable[hashKey] ){
+					if ( optPfxKeyEntry.affixKey == pfxEntry.affixKey ) {
+						while( optPfxKeyEntry.nextElementWithKey != null ) {
+							if ( optPfxKeyEntry.isSimilarObject(pfxEntry) ) {
+								optPfxKeyEntry.extendObject(pfxEntry);
+								return true;
+							}
+							optPfxKeyEntry = optPfxKeyEntry.nextElementWithKey; 
+						}
+						if ( optPfxKeyEntry.isSimilarObject(pfxEntry) ) {
+							optPfxKeyEntry.extendObject(pfxEntry);
+							return true;
+						}
+						optPfxKeyEntry.nextElementWithKey = optPfxEntry;
+						return true;
+					}
+				}
+				_optPrefixKeyTable[hashKey].push(optPfxEntry);
+				_optPrefixKeyTable[hashKey].sortOn("affixKey");
+			}				
+			return true;
+			
+		}
+
+		
+		private function addOptSuffixEntry(sfxEntry:SuffixEntry):Boolean {
+			var optSfxEntry:OptimizedSuffixEntry
+
+			//insert suffix key table....
+			if ( _optSuffixKeyTable[sfxEntry.affixKey] == undefined ) {
+				optSfxEntry = new OptimizedSuffixEntry(sfxEntry);
+				optSfxEntry.attributeManager = this;
+				_optSuffixKeyTable[sfxEntry.affixKey] = optSfxEntry;
+			}
+			else {
+				var optSfxKeyEntry:OptimizedSuffixEntry = _optSuffixKeyTable[sfxEntry.affixKey];
+				while( optSfxKeyEntry.nextElementWithKey != null ) {
+					if ( optSfxKeyEntry.isSimilarObject(sfxEntry) ) {
+						optSfxKeyEntry.extendObject(sfxEntry);
+						return true;
+					}
+					optSfxKeyEntry = optSfxKeyEntry.nextElementWithKey; 
+				}
+				if ( optSfxKeyEntry.isSimilarObject(sfxEntry) ) {
+					optSfxKeyEntry.extendObject(sfxEntry);
+					return true;
+				}
+				optSfxEntry = new OptimizedSuffixEntry(sfxEntry);
+				optSfxEntry.attributeManager = this;
+				optSfxKeyEntry.nextElementWithKey = optSfxEntry;
+			}				
+			return true;
+			
+		}
+		
+		
+		
+		private function addPrefixEntry(pfxEntry:PrefixEntry):Boolean {
+			// We may combine prefix/suffix insertion into one function in the future, it could be good for reduce the code size.
+			// Since may there is some difference between prefix and suffix, so leave it with different class and different table....
+			// need better consideration for performance and code style in next step...
+			var flagChar:String;
+			flagChar = String.fromCharCode(pfxEntry.flag);
+			// insert prefix flag table...
+			if ( _prefixFlagTable[flagChar] == undefined )
+				_prefixFlagTable[flagChar] = pfxEntry;
+			else {
+				var pfxFlagEntry:PrefixEntry = _prefixFlagTable[flagChar];
+				while( pfxFlagEntry.nextElementWithFlag != null ) {
+					pfxFlagEntry = pfxFlagEntry.nextElementWithFlag; 
+				}
+				pfxFlagEntry.nextElementWithFlag = pfxEntry;
+			}
+			
+			//insert prefix key table....
+			if ( _prefixKeyTable[pfxEntry.affixKey] == undefined ) 
+				_prefixKeyTable[pfxEntry.affixKey] = pfxEntry;
+			else {
+				var pfxKeyEntry:PrefixEntry = _prefixKeyTable[pfxEntry.affixKey];
+				while( pfxKeyEntry.nextElementWithKey != null ) {
+					pfxKeyEntry = pfxKeyEntry.nextElementWithKey; 
+				}
+				pfxKeyEntry.nextElementWithKey = pfxEntry;
+			}			
+			return true;
+		}
+		
+		private function addSuffixEntry(sfxEntry:SuffixEntry ):Boolean {
+			// We may combine prefix/suffix insertion into one function in the future, it could be good for reduce the code size.
+			// Since may there is some difference between prefix and suffix, so leave it with different class and different table....
+			// need better consideration for performance and code style in next step...
+			var flagChar:String;
+			flagChar = String.fromCharCode(sfxEntry.flag);
+			// insert suffix flag table...
+			if ( _suffixFlagTable[flagChar] == undefined )
+				_suffixFlagTable[flagChar] = sfxEntry;
+			else {
+				var sfxFlagEntry:SuffixEntry = _suffixFlagTable[flagChar];
+				while( sfxFlagEntry.nextElementWithFlag != null ) {
+					sfxFlagEntry = sfxFlagEntry.nextElementWithFlag; 
+				}
+				sfxFlagEntry.nextElementWithFlag = sfxEntry;
+			}
+			
+			//insert suffix key table....
+			if ( _suffixKeyTable[sfxEntry.affixKey] == undefined ) 
+				_suffixKeyTable[sfxEntry.affixKey] = sfxEntry;
+			else {
+				var sfxKeyEntry:SuffixEntry = _suffixKeyTable[sfxEntry.affixKey];
+				while( sfxKeyEntry.nextElementWithKey != null ) {
+					sfxKeyEntry = sfxKeyEntry.nextElementWithKey; 
+				}
+				sfxKeyEntry.nextElementWithKey = sfxEntry;
+			}				
+			
+			return true;
+		}
+		
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		public function addAffixEntry2(affixFlag:int, stripString:String, affixValue:String, conditionsStr:String, morph:String = "", permission:Boolean = false, affixType:int = 0):Boolean{
+			if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+			if ( affixType == 0 ) {
+				if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+				var pfxEntry:PrefixEntry = new PrefixEntry(affixFlag,stripString,affixValue,conditionsStr,morph,permission);
+				pfxEntry.attributeManager = this;
+				addPrefixEntry(pfxEntry);
+			}else {
+				if ( stripString == null || affixValue == null || conditionsStr==null || conditionsStr=="" ) return false;
+				var sfxEntry:SuffixEntry = new SuffixEntry(affixFlag,stripString,affixValue,conditionsStr,morph,permission);
+				sfxEntry.attributeManager = this;
+				addSuffixEntry(sfxEntry);	
+			}
+			return true;
+		}
+		
+		public function get prefixFlagTable():Array {
+			return this._prefixFlagTable;
+		}
+		
+		public function get prefixKeyTable():Array {
+			return this._prefixKeyTable;
+		}
+		
+		public function get suffixFlagTable():Array {
+			return this._suffixFlagTable;
+		}
+		
+		public function get suffixKeyTable():Array {
+			return this._suffixKeyTable;
+		}
+		
+		public function set forbiddenWord(value:Number) :void {
+			this._forbiddenWord = value;
+		}
+		
+		public function get forbiddenWord():Number {
+			return this._forbiddenWord;
+		}
+		
+		public function set ignoredChars(value:String ) :void {
+			this._ignoredChars = value;
+		}
+		
+		public function get ignoredChars():String {
+			return this._ignoredChars;
+		}
+		
+		public function set keyString(value:String):void {
+			this._keyString = value;
+		}
+		
+		public function get keyString():String {
+			if ( this._keyString == null ) this._keyString=InternalConstants.SPELL_KEYSTRING;
+			return this._keyString;
+		}
+		
+		public function set tryString(value:String):void {
+			this._tryString = value;
+		}
+		
+		public function get tryString():String {
+			return this._tryString;
+		}
+		
+		public function get contClasses():Dictionary {
+			return _contClasses;
+		}
+		
+		
+		public function set noSuggest(value:Number ):void {
+			this._noSuggest = value;
+		}
+		public function get noSuggest():Number {
+			return this._noSuggest;
+		}
+		
+		public function get simpleFilterTable():Array {
+			return this._simpleFilterTable;
+		}
+		
+		public function get iconvFilterTable():Array {
+			return this._iconvFilterTable;
+		}
+		
+		public function get oconvFilterTable():Array {
+			return this._oconvFilterTable;
+		}
+		
+/*		public function get phoneTable():PhoneticTable {
+			return this._phoneTable;
+		}
+*/		
+		public function get breakTable():Array {
+			return this._breakTable;
+		}
+		public function get aliasfTable():Array{
+			return this._aliasfTable;
+		}
+
+		
+		public function get mapFilterTable():Array {
+			return this._mapFilterTable;
+		}
+				
+	/*This function is used for supporting ICONV/OCONV rule. This function is called whenever an input or output conversion is needed.*/			
+		public function conv(word:String,convWord:Array,ioflag:Boolean):Boolean{
+			var searchIndex:int=0;
+			var change:Boolean=false;
+			var wspace:String;
+			var convTable:Array=(ioflag)?this._iconvFilterTable:this._oconvFilterTable;
+			if ( (convTable==null) || (convTable.length == 0) ) return false;
+			for ( var i:int = 0; i < convTable.length; ++i ) {
+				while ( (searchIndex = word.indexOf( convTable[i].matchString,searchIndex)) != -1 ){
+					searchIndex = searchIndex + convTable[i].matchString.length;
+					wspace = word.substr(0, searchIndex-convTable[i].matchString.length) + 
+						convTable[i].replacement + 
+						word.substr(searchIndex);
+					if(wspace)
+						word=wspace;
+					change=true;
+				}
+				
+			}
+			convWord.push(wspace);
+			return change;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SpellingInfo.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SpellingInfo.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SpellingInfo.as
new file mode 100644
index 0000000..2b874dd
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SpellingInfo.as
@@ -0,0 +1,32 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	public class SpellingInfo
+	{
+		public var Info:Number;
+		public function SpellingInfo(information:Number)
+		{
+			Info=information;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyDictionary.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyDictionary.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyDictionary.as
new file mode 100644
index 0000000..4b80d7c
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyDictionary.as
@@ -0,0 +1,207 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+
+	import com.adobe.linguistics.spelling.core.container.HashTable;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.error.*;
+	import com.adobe.linguistics.spelling.core.utils.StringUtils;
+	
+	import flash.utils.Dictionary;
+	
+	
+	public class SquigglyDictionary
+	{
+		private var _hashtbl:HashTable;
+		private var _forbiddenword:int;
+		private var _ignoredCharSet:String;
+		private var _flag_mode:int;
+		private var _languageCode:String;
+
+
+
+		public function SquigglyDictionary(attrMgr:LinguisticRule)
+		{
+			_hashtbl = new HashTable( true ); // useWeakReferences:Boolean = true
+			
+			if ( !attrMgr) {
+				_forbiddenword = InternalConstants.FORBIDDENWORD;
+				_ignoredCharSet = null;
+				_flag_mode = InternalConstants.FLAG_CHAR;
+				_languageCode = null;
+			}
+		}
+		
+		private function set forbiddenword(value:int ) :void {
+			this._forbiddenword = value;
+		}
+		
+		public function get forbiddenword():int {
+			return this._forbiddenword;
+		}
+		
+		private function set ignoredCharSet(value:String):void {
+			this._ignoredCharSet = value;
+		}
+		
+		public function get ignoredCharSet():String {
+			return this._ignoredCharSet;
+		}
+		
+		private function set flag_mode(value:int):void {
+			this._flag_mode = value;
+		} 
+		
+		public function get flag_mode():int {
+			return this._flag_mode;
+		}
+		
+		private function set languageCode(value:String ) :void {
+			this._languageCode = value;
+		}
+		
+		public function get languageCode():String {
+			return this._languageCode;
+		}
+
+		public function containsKey(key:String ):Boolean
+		{
+			return _hashtbl.containsKey(key );
+		}
+		
+		public function getElement( key:String ):HashEntry {
+			var res:* = _hashtbl.getElement(key );
+			return (res is HashEntry) ? res:null;
+//			return _hashtbl.getElement(key );
+		}
+		
+		public function put(key:String, affixString:String=null, description:String = null):Boolean {
+			return addWord( key, affixString, description );	
+		}
+		
+		public function get dictionary():Dictionary {
+			return this._hashtbl.hashMap;
+		}
+		
+		public function filter( callback:Function, thisObject:* = null):Array {
+			var res:Array = new Array();
+			var index:int;
+			var dict:Dictionary = this._hashtbl.hashMap;
+			for ( var key:* in dict ) {
+				if ( callback( key, index, res ) ) {
+					res.push( key );
+				}
+			}
+			
+			return (res.length == 0) ? null: res;
+		}
+		
+		
+		public function addWord( word:String, affix:String = null, desc:String = null ) :Boolean {
+			var res:Boolean = false;
+			if ( word == null ) return false;
+			var captype:int = StringUtils.getCapType(word);
+			if ( addWordWithAffix(word,affix,desc,false ) )
+				res = true;
+			addHiddenCapitalizedWord(word,captype, affix,desc);
+			return res;		
+		}
+
+		private function addHiddenCapitalizedWord( word:String, captype:int, affix:String=null, desc:String=null ) :Boolean {
+			// add inner capitalized forms to handle the following allcap forms:
+			// Mixed caps: OpenOffice.org -> OPENOFFICE.ORG
+			// Allcaps with suffixes: CIA's -> CIA'S
+			if (((captype == InternalConstants.HUHCAP) || (captype == InternalConstants.HUHINITCAP) ||((captype == InternalConstants.ALLCAP) && (affix != null))) &&
+			!((affix != null) && HashEntry.TESTAFF(affix, _forbiddenword))) {
+				affix += String.fromCharCode(InternalConstants.ONLYUPCASEFLAG);
+				word = word.toLocaleLowerCase();
+				word = word.charAt(0).toLocaleUpperCase() + word.substr(1);
+				addWordWithAffix(word,affix,desc,true);
+			}
+			return true;
+		}
+
+		private function addWordWithAffix( word:String, affix:String, desc:String, onlyupcase:Boolean ):Boolean {
+			var upcasehomonym:Boolean = false;
+			if (_ignoredCharSet != null) {
+				word = StringUtils.removeIgnoredChars(word, _ignoredCharSet);
+			}
+//ToDo: the following comment should be removed after we have complex-affix support.
+//
+//			if (complexprefixes) {
+//				reverseword(word);
+//			}
+//        hp->var = H_OPT;
+//        if (aliasm) {
+//            hp->var += H_OPT_ALIASM;
+//            store_pointer(hpw + wbl + 1, get_aliasm(atoi(desc)));
+//        } else {
+//            strcpy(hpw + wbl + 1, desc);
+//            if (complexprefixes) {
+//                if (utf8) reverseword_utf(HENTRY_DATA(hp));
+//                else reverseword(HENTRY_DATA(hp));
+//            }
+//        }
+//        if (strstr(HENTRY_DATA(hp), MORPH_PHON)) hp->var += H_OPT_PHON;
+			
+			if ( _hashtbl.containsKey(word) ) {
+
+				var hentry:HashEntry = _hashtbl.getElement(word);
+				while ( hentry.next != null ) {
+					// remove hidden onlyupcase homonym
+					if ( !onlyupcase ) {
+						if ( (hentry.affixFlagVector != null) && hentry.testAffix(InternalConstants.ONLYUPCASEFLAG) ) {
+							hentry.affixFlagVector = affix;
+							hentry.variableFields = desc; /* need a better implementation,refer the beginning of this function */
+							return true;
+						}
+					}else {
+						upcasehomonym = true;
+					}
+					hentry = hentry.next;
+				}
+				// remove hidden onlyupcase homonym
+				if ( !onlyupcase ) {
+					if ( (hentry.affixFlagVector != null) && hentry.testAffix(InternalConstants.ONLYUPCASEFLAG) ) {
+						hentry.affixFlagVector = affix;
+						hentry.variableFields = desc; /* need a better implementation,refer the beginning of this function */
+						return true;
+					}
+				}else {
+					upcasehomonym = true;
+				}
+
+				if ( !upcasehomonym ) {
+					hentry.addEntry(affix,desc);
+					return true;
+				}else
+					return false;
+			}else {
+				_hashtbl.put(word, new HashEntry(affix,desc) );
+				return true;
+			}
+		}		
+
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyEngine.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyEngine.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyEngine.as
new file mode 100644
index 0000000..d7fdc5c
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SquigglyEngine.as
@@ -0,0 +1,426 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+
+	import com.adobe.linguistics.spelling.core.env.ExternalConstants;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.utils.*;
+	
+	public class SquigglyEngine
+	{
+
+		private var _ignoreCappedWord:Boolean;		// Hello is always correct
+		private var _ignoreAllUpperCase:Boolean;	// HELLO is always correct
+		private var _ignoreWordWithNumber:Boolean;	// win2003 is always correct
+		private var wordBreak:Array;				// Used to hold BREAK characters for BREAK rule
+		private const SPELL_COMPOUND:int =				(1 << 0);
+		private const SPELL_FORBIDDEN:int =				(1 << 1);
+		private const SPELL_ALLCAP:int =				(1 << 2);
+		private const SPELL_NOCAP:int =					(1 << 3);
+		private const SPELL_INITCAP:int =				(1 << 4);
+
+		private const MAXDIC:int =						20;
+		private const MAXSHARPS:int =					5;
+
+		private var attributeMgr:LinguisticRule;
+		private var dictMgr:DictionaryManager;
+		private var sugestionMgr:SuggestionManager;
+		private var encoding:String;
+		private var wordbreak:Array;//an Array that holds the word breaks
+		private var langCode:int;
+		private var complexPrefixes:int;
+		private var maxWordLength:int;
+
+		public function SquigglyEngine( rule:LinguisticRule, dict:SquigglyDictionary )
+		{
+			if ( rule == null ) throw new Error("illegal argument for constructor", 200901);
+			if ( dict == null ) throw new Error("illegal argument for constructor", 200901);
+			
+			maxWordLength = InternalConstants.MAXWORDLEN;
+			
+			dictMgr = new DictionaryManager();
+			dictMgr.addDictionary(dict);
+			attributeMgr = rule;
+			attributeMgr.dictionaryManager = dictMgr;
+			sugestionMgr = new SuggestionManager( rule, false);
+			this.wordbreak=attributeMgr.breakTable;
+			this.ignoreWordWithNumber = false;
+			this.ignoreCappedWord = false;
+			this.ignoreAllUpperCase = false;
+
+		}
+		
+		public function set ignoreWordWithNumber( value:Boolean):void {
+			this._ignoreWordWithNumber =value;
+		}
+		public function get ignoreWordWithNumber():Boolean {
+			return this._ignoreWordWithNumber;
+		}
+		
+		public function set ignoreCappedWord(value:Boolean):void {
+			this._ignoreCappedWord = value;
+		}
+		public function get ignoreCappedWord():Boolean {
+			return this._ignoreCappedWord;
+		}
+		
+		public function set ignoreAllUpperCase(value:Boolean ):void {
+			this._ignoreAllUpperCase = value;
+		}
+		public function get ignoreAllUpperCase():Boolean {
+			return this._ignoreAllUpperCase;
+		}
+		
+		public function set fastMode(value:Boolean ) :void {
+			this.sugestionMgr.fastMode = value;
+		}
+		
+		public function get fastMode():Boolean {
+			return this.sugestionMgr.fastMode;
+		}
+		
+		public function addDictionary( dict:SquigglyDictionary ) : Boolean {
+			return dictMgr.addDictionary(dict);
+		}
+		
+		public function spell( word:String ) :Boolean {
+			if ( word.length > maxWordLength ) return false;
+			
+			word = StringUtils.normalize(word);
+			
+			var captype:int = InternalConstants.NOCAP;
+			var hasNumber:Boolean =false; //assuming that there are no numbers;
+			var abbv:int = 0;
+			var i:int;
+			var rv:HashEntry = null;
+			var info:SpellingInfo = new SpellingInfo(0);
+			var wspace:String;
+			// input conversion USING ICONV TABLE
+/*	//Commented code is a unit test code
+			var teststr:String="marùvîà ";
+			var teststr2:String;
+this.attributeMgr.conv(teststr,convWord,true);
+	teststr2=convWord.pop();
+	if(teststr2){
+	trace("Called Word "+teststr+"converted word "+teststr2);
+	}
+	else 
+	trace("NUUUllll");
+*/
+
+			var convWord:Array=new Array;
+			if(this.attributeMgr && this.attributeMgr.iconvFilterTable && this.attributeMgr.iconvFilterTable.length!=0){
+			this.attributeMgr.conv(word,convWord,InternalConstants.CONV_ICONV);
+			wspace=convWord.pop();
+			if(wspace) word=wspace;
+			}
+			
+			// first skip over any leading or trailing blanks
+			word = StringUtils.trim( word );
+			
+			// now strip off any trailing periods (recording their presence)
+			for ( i = word.length-1; (i>=0) && (word.charCodeAt(i) == 46) ; --i ) { // '.'
+				abbv++;
+			}
+			word = word.substr(0, word.length- abbv );
+			captype = StringUtils.getCapType(word);
+			hasNumber=StringUtils.getHasNumber(word);
+			if ( (dictMgr.isEmpty()) || (word.length == 0) ) return false;
+			
+			// allow numbers with dots, dashes and commas (but forbid double separators: "..", "--" etc.)
+			const NBEGIN:int = 0, NNUM:int=1, NSEP:int=2;
+			var nstate:int = NBEGIN;
+			var charCode:int;
+			for ( i=0 ; i < word.length ; ++i ) {
+				charCode =  word.charCodeAt(i);
+				if ( (charCode <= 57 ) && ( charCode >= 48) ) { // '0' to '9'
+					nstate = NNUM;
+				}else if ( (charCode==44) || (charCode==45) || (charCode==46) ) { //',' or '.' or '-'
+					if ( (nstate == NSEP) || ( i==0 ) ) return false;
+					nstate = NSEP;
+				}else break;
+			}
+			if ( (i==word.length) && ( nstate == NNUM ) ) return true;//checks if all are just numbers
+			// ignore word with Number.
+			if ( ignoreWordWithNumber && hasNumber)return true;//Ignore word with numbers!
+				
+			// ignore cappitalized word  or ignore all upper case word.
+			if ( (ignoreCappedWord &&( (captype&InternalConstants.HUHINITCAP) || (captype&InternalConstants.INITCAP))&&(hasNumber==false) ) || (ignoreAllUpperCase&&(captype & InternalConstants.ALLCAP)&&(hasNumber==false)) ) return true;	//return only if it does not have number	
+			
+			
+			switch(captype) {
+				case InternalConstants.HUHCAP:
+				case InternalConstants.HUHINITCAP:
+				case InternalConstants.NOCAP:
+					rv = checkWord(word,info);
+					if ( (abbv!=0) && (rv == null ) ) {
+						word += ".";
+						rv = checkWord(word,info);
+					}
+					break;
+				case InternalConstants.ALLCAP:
+					rv = checkWord(word,info);
+					if( rv ) break;
+					if ( (abbv!=0 ) ) {
+						word +=".";
+						rv = checkWord(word,info);
+						if ( rv ) break;
+					}
+					// ToDo:   Spec. prefix handling for Catalan, French, Italian:
+					// prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia).
+					// need better understand...
+					
+					//sharps handle....
+
+					word = word.charAt(0).toUpperCase()+word.slice(1).toLocaleLowerCase();
+					
+				case InternalConstants.INITCAP: 
+					if (captype == InternalConstants.INITCAP) info.Info +=ExternalConstants.SPELL_INITCAP;
+					wspace = word.toLocaleLowerCase();
+					rv = checkWord(word,info);
+					if (captype == InternalConstants.INITCAP) info.Info -=ExternalConstants.SPELL_INITCAP;
+					
+					// forbid bad capitalization
+					// (for example, ijs -> Ijs instead of IJs in Dutch)
+					// use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag)
+					if (info.Info & ExternalConstants.SPELL_FORBIDDEN) {
+						rv = null;
+					}
+					
+					if ( rv && (captype == InternalConstants.ALLCAP ) ) {
+						if ( attributeMgr && rv.affixFlagVector && attributeMgr.keepCase && rv.testAffix(attributeMgr.keepCase) ) rv = null;
+					}
+					if ( rv) break;
+					
+					rv = checkWord(wspace,info);
+					if ( !rv && abbv ) {
+						wspace += ".";
+						rv = checkWord(wspace,info);
+						if ( !rv) {
+							word += ".";
+							if (captype == InternalConstants.INITCAP) info.Info +=ExternalConstants.SPELL_INITCAP;
+							rv = checkWord(word,info);
+							if (captype == InternalConstants.INITCAP) info.Info -=ExternalConstants.SPELL_INITCAP;
+							if ( rv && (captype == InternalConstants.ALLCAP ) ) {
+								if ( attributeMgr && rv.affixFlagVector && attributeMgr.keepCase && rv.testAffix(attributeMgr.keepCase) ) rv = null;
+							}
+						}
+					} 
+					if ( rv && (captype == InternalConstants.ALLCAP ) ) {
+						if ( attributeMgr && rv.affixFlagVector && attributeMgr.keepCase && rv.testAffix(attributeMgr.keepCase) ) rv = null;
+					}
+					break;
+				default:
+			}
+			
+			if ( rv ) return true;
+			
+			//implementation break-table... recursive breaking at break points
+			
+			if(wordbreak){
+				var nbr:int=0;
+				var parseArr:Array;
+				var searchIndex:int=0;
+				for(i=0; i<wordbreak.length;i++){
+					//Search for number of break points in this word
+					searchIndex=0;
+					wspace=word;
+					while (wspace && ((searchIndex=wspace.indexOf(wordbreak[i])) != -1 )) {
+						nbr++;
+						if(nbr>InternalConstants.MAX_WORD_BREAKS) return false;//Limiting maximum Word breaks
+						if(searchIndex<word.length)wspace=wspace.substr(searchIndex+1);
+					}		
+				}
+				 
+				
+				for(var j:int=0; j<wordbreak.length;j++){
+				
+					if(word.search(wordbreak[j])!=-1 && (parseArr=word.split(wordbreak[j]))!=null)
+					{
+									
+						for(i=0;i<parseArr.length;i++)
+							if(! spell(parseArr[i]) ) return false;//keep checking all parts of the input word. If any part is wrongly spelt send false
+						
+						return true;//no part is spelled wrong so send correct
+					}
+								
+				}
+							
+			}
+		
+			return false;
+		}
+		
+		public function suggest( word:String ) : Array {
+			if ( word.length > maxWordLength ) return null;
+			var captype:int = InternalConstants.NOCAP;
+			var capwords:int = 0;
+
+			var abbv:int = 0;
+			var i:int,ns:int;
+			var wspace:String;
+			var slst:Array = new Array();
+			var convWord:Array=new Array;
+			// input conversion USING ICONV TABLE
+			if(this.attributeMgr && this.attributeMgr.iconvFilterTable.length!=0){
+				this.attributeMgr.conv(word,convWord,InternalConstants.CONV_ICONV);
+			wspace=convWord.pop();
+			if(wspace)word=wspace;
+			}
+			
+			// first skip over any leading or trailing blanks
+			word = StringUtils.trim( word );
+			// now strip off any trailing periods (recording their presence)
+			for ( i = word.length-1; (i>=0) && (word.charCodeAt(i) == 46) ; --i ) { // '.'
+				abbv++;
+			}
+			word = word.substr(0, word.length- abbv );
+			captype = StringUtils.getCapType(word);
+			if ( (dictMgr.isEmpty()) || (word.length == 0) ) return null;
+			switch(captype) {
+				case InternalConstants.NOCAP: {
+					ns = sugestionMgr.suggest( slst, word, InternalConstants.NOCAP );
+					break;
+				}
+				case InternalConstants.INITCAP:{
+					capwords = 1;
+					ns = sugestionMgr.suggest( slst, word, InternalConstants.INITCAP );
+					if ( ns ==  -1) break;
+					wspace = word.toLocaleLowerCase();
+					ns = sugestionMgr.suggest( slst, wspace, InternalConstants.NOCAP );
+					break;
+				}
+				case InternalConstants.HUHINITCAP:{ 
+					capwords = 1;
+				}
+				case InternalConstants.HUHCAP: { // ToDo: still a lot of work...
+					ns = sugestionMgr.suggest( slst, word, InternalConstants.HUHCAP );
+					break;
+				}
+				case InternalConstants.ALLCAP: {
+					wspace = word.toLocaleLowerCase();
+					ns = sugestionMgr.suggest( slst, wspace, InternalConstants.NOCAP );
+					if ( ns ==  -1) break;
+					if ( this.attributeMgr.keepCase && spell(word ) ) {
+						//ns = insert_sug(slst, wspace, ns); ToDo
+					}
+					wspace = word.charAt(0).toUpperCase()+word.slice(1).toLocaleLowerCase();	
+					ns = sugestionMgr.suggest( slst, wspace, InternalConstants.INITCAP );
+					break;
+				}
+			}
+			
+			// try ngram approach since found nothing
+			if ( this.attributeMgr && (this.attributeMgr.maxNgramSuggestions != 0)) {
+				ns = sugestionMgr.nsuggest(slst,word);
+			}
+			
+			// try dash suggestion (Afo-American -> Afro-American)
+			
+			// capitalize
+			if (capwords) {
+				for ( i=0;i<slst.length; ++i ) {
+					slst[i] = slst[i].charAt(0).toUpperCase()+slst[i].slice(1);	
+				}
+			}
+			
+			// expand suggestions with dot(s)
+			if ( abbv && this.attributeMgr.suggestionsWithDots ) {
+				for ( i=0;i<slst.length; ++i ) {
+					slst[i] += ".";	
+				}
+				
+			}
+			
+			// remove bad capitalized and forbidden forms
+
+			// remove original one
+			for ( i=0;i<slst.length;++i) {
+				if ( slst[i] == word ) 
+					slst.splice(i,1);
+			}
+			
+			// remove duplications
+			
+			// output conversion
+			
+			if(this.attributeMgr && this.attributeMgr.oconvFilterTable && this.attributeMgr.oconvFilterTable.length!=0){
+				for(i=0;i<slst.length;++i){
+					if(this.attributeMgr.conv(slst[i],convWord,InternalConstants.CONV_OCONV))	
+					{wspace=convWord.pop();delete(slst[i]); slst[i]=wspace;} 
+				}
+			}
+			
+			// if suggestions removed by nosuggest, onlyincompound parameters
+
+
+			return (slst.length!=0) ? slst :null;
+		}
+		
+		private function checkWord( word:String, info:SpellingInfo ):HashEntry {
+			var i:int;
+			var he:HashEntry = null;
+			if ( attributeMgr.ignoredChars )  {
+				word = StringUtils.removeIgnoredChars(word, attributeMgr.ignoredChars);
+			}
+			// word reversing wrapper for complex prefixes
+			/*
+			if(complexprefixes) {
+				word=reverseword(word);
+			}
+			*/
+			
+			// look word in hash table
+			for ( i=0; i < dictMgr.dictonaryList.length && !he; ++i ) {
+				he = dictMgr.dictonaryList[i].getElement(word);
+				// check forbidden and onlyincompound words
+				if ( he && (he.affixFlagVector != null) && 
+					((attributeMgr) && ( he.testAffix(attributeMgr.forbiddenWord)))
+				
+				) {
+					// ToDo: LANG_hu section: set dash information for suggestions
+					return null;
+				}
+				// ToDo: he = next not needaffix, onlyincompound homonym or onlyupcase word
+/*				while (he && (he.affixFlagVector) &&
+					((attributeMgr.needAffix && testAffix(he.affixFlagVector, attributeMgr.needAffix)) ||
+						(pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) ||
+						(info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen))
+					)) //he = he.next; should maintain a next homonym which is not being maintained as of now next_homonym;
+*/			}
+					
+			// check with affixes
+			if ( !he && attributeMgr ) {
+				he = attributeMgr.affixCheck2(word,0,0);
+				//DO not allow affixed forms of forbidden words
+				if ( he && (he.affixFlagVector != null) && (attributeMgr) && he.testAffix(attributeMgr.forbiddenWord) ) {
+					// ToDo: LANG_hu section: set dash information for suggestions
+					return null;
+				}
+			}
+			
+			return he;
+		}
+		
+
+	}
+}
\ No newline at end of file


[17/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project-sve.pbxproj
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project-sve.pbxproj b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project-sve.pbxproj
new file mode 100644
index 0000000..1cfdfbc
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project-sve.pbxproj
@@ -0,0 +1,329 @@
+// !$*UTF8*$!
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1D534A45135DF0D20045AD31 /* Adobe AIR.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D534A44135DF0D20045AD31 /* Adobe AIR.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
+		1DBD233A1328578300B5B085 /* TestNativeExtension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DBD23391328578300B5B085 /* TestNativeExtension.cpp */; };
+		8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		1D534A44135DF0D20045AD31 /* Adobe AIR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "Adobe AIR.framework"; path = "../../../../../../../AIR-SDKs/apa290/runtimes/air/mac/Adobe AIR.framework"; sourceTree = SOURCE_ROOT; };
+		1DBD23391328578300B5B085 /* TestNativeExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestNativeExtension.cpp; sourceTree = "<group>"; };
+		32DBCF5E0370ADEE00C91783 /* TestNativeExtension_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestNativeExtension_Prefix.pch; sourceTree = "<group>"; };
+		8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		8DC2EF5B0486A6940098B216 /* TestNativeExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TestNativeExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8DC2EF560486A6940098B216 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
+				1D534A45135DF0D20045AD31 /* Adobe AIR.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DFFF38A50411DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8DC2EF5B0486A6940098B216 /* TestNativeExtension.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 /* TestNativeExtension */ = {
+			isa = PBXGroup;
+			children = (
+				1DBD23391328578300B5B085 /* TestNativeExtension.cpp */,
+				08FB77AEFE84172EC02AAC07 /* Classes */,
+				32C88DFF0371C24200C91783 /* Other Sources */,
+				089C1665FE841158C02AAC07 /* Resources */,
+				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+				034768DFFF38A50411DB9C8B /* Products */,
+			);
+			name = TestNativeExtension;
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
+				1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
+			);
+			name = "External Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		089C1665FE841158C02AAC07 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				8DC2EF5A0486A6940098B216 /* Info.plist */,
+				089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		08FB77AEFE84172EC02AAC07 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1D534A44135DF0D20045AD31 /* Adobe AIR.framework */,
+				1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				0867D6A5FE840307C02AAC07 /* AppKit.framework */,
+				D2F7E79907B2D74100F64583 /* CoreData.framework */,
+				0867D69BFE84028FC02AAC07 /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		32C88DFF0371C24200C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				32DBCF5E0370ADEE00C91783 /* TestNativeExtension_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		8DC2EF500486A6940098B216 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		8DC2EF4F0486A6940098B216 /* TestNativeExtension */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "TestNativeExtension" */;
+			buildPhases = (
+				8DC2EF500486A6940098B216 /* Headers */,
+				8DC2EF520486A6940098B216 /* Resources */,
+				8DC2EF540486A6940098B216 /* Sources */,
+				8DC2EF560486A6940098B216 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = TestNativeExtension;
+			productInstallPath = "$(HOME)/Library/Frameworks";
+			productName = TestNativeExtension;
+			productReference = 8DC2EF5B0486A6940098B216 /* TestNativeExtension.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "TestNativeExtension" */;
+			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07 /* TestNativeExtension */;
+			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8DC2EF4F0486A6940098B216 /* TestNativeExtension */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		8DC2EF520486A6940098B216 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8DC2EF540486A6940098B216 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1DBD233A1328578300B5B085 /* TestNativeExtension.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				089C1667FE841158C02AAC07 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB91AE08733DA50010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/../../../../../../../Flex-SDKs/NE_SB-Overlay/runtimes/air/mac\"",
+					"\"$(SRCROOT)/../../../../../../../AIR-SDKs/apa290/runtimes/air/mac\"",
+				);
+				FRAMEWORK_VERSION = A;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TestNativeExtension_Prefix.pch;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"/Library/Frameworks/Adobe\\ AIR.framework/Versions/1.0",
+				);
+				OTHER_CFLAGS = "-fvisibility=hidden";
+				OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
+				OTHER_LDFLAGS = "";
+				PRODUCT_NAME = TestNativeExtension;
+				WRAPPER_EXTENSION = framework;
+			};
+			name = Debug;
+		};
+		1DEB91AF08733DA50010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SRCROOT)/../../../../../../../Flex-SDKs/NE_SB-Overlay/runtimes/air/mac\"",
+					"\"$(SRCROOT)/../../../../../../../AIR-SDKs/apa290/runtimes/air/mac\"",
+				);
+				FRAMEWORK_VERSION = A;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = TestNativeExtension_Prefix.pch;
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Frameworks";
+				PRODUCT_NAME = TestNativeExtension;
+				WRAPPER_EXTENSION = framework;
+			};
+			name = Release;
+		};
+		1DEB91B208733DA50010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Debug;
+		};
+		1DEB91B308733DA50010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "TestNativeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91AE08733DA50010E9CD /* Debug */,
+				1DEB91AF08733DA50010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "TestNativeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91B208733DA50010E9CD /* Debug */,
+				1DEB91B308733DA50010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.pbxproj
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.pbxproj b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..f3d08b8
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.pbxproj
@@ -0,0 +1,428 @@
+// !$*UTF8*$!
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		1DBD233A1328578300B5B085 /* HunspellNativeExtension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DBD23391328578300B5B085 /* HunspellNativeExtension.cpp */; };
+		1DE3D070144F354C0007B73C /* Adobe AIR.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DE3D06F144F354C0007B73C /* Adobe AIR.framework */; };
+		8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+		8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
+		F623A55B159CA5DE00A209C5 /* EncConv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F623A559159CA5DE00A209C5 /* EncConv.cpp */; };
+		F623A55C159CA5DE00A209C5 /* EncConv.h in Headers */ = {isa = PBXBuildFile; fileRef = F623A55A159CA5DE00A209C5 /* EncConv.h */; };
+		F6275F5715AF16260062D479 /* libsicudata.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6275F5415AF16260062D479 /* libsicudata.a */; };
+		F6275F5815AF16260062D479 /* libsicui18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6275F5515AF16260062D479 /* libsicui18n.a */; };
+		F6275F5915AF16260062D479 /* libsicuuc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F6275F5615AF16260062D479 /* libsicuuc.a */; };
+		F6275F6715B40E5C0062D479 /* Utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F6275F6615B40E5C0062D479 /* Utilities.h */; };
+		F674FB6415996E9C00BAB506 /* HunspellNativeExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = F674FB6315996E9C00BAB506 /* HunspellNativeExtension.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
+		0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
+		089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
+		1DBD23391328578300B5B085 /* HunspellNativeExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HunspellNativeExtension.cpp; sourceTree = "<group>"; };
+		1DE3D06F144F354C0007B73C /* Adobe AIR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "Adobe AIR.framework"; path = "/Applications/Adobe Flash Builder 4.5/sdks/4.5.1-air3.0/runtimes/air/mac/Adobe AIR.framework"; sourceTree = "<absolute>"; };
+		32DBCF5E0370ADEE00C91783 /* HunspellNativeExtension_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HunspellNativeExtension_Prefix.pch; sourceTree = "<group>"; };
+		8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		8DC2EF5B0486A6940098B216 /* HunspellNativeExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HunspellNativeExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
+		F623A559159CA5DE00A209C5 /* EncConv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EncConv.cpp; sourceTree = "<group>"; };
+		F623A55A159CA5DE00A209C5 /* EncConv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncConv.h; sourceTree = "<group>"; };
+		F6275F5415AF16260062D479 /* libsicudata.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsicudata.a; sourceTree = "<group>"; };
+		F6275F5515AF16260062D479 /* libsicui18n.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsicui18n.a; sourceTree = "<group>"; };
+		F6275F5615AF16260062D479 /* libsicuuc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libsicuuc.a; sourceTree = "<group>"; };
+		F6275F6615B40E5C0062D479 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utilities.h; sourceTree = "<group>"; };
+		F674FB6315996E9C00BAB506 /* HunspellNativeExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HunspellNativeExtension.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		8DC2EF560486A6940098B216 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */,
+				1DE3D070144F354C0007B73C /* Adobe AIR.framework in Frameworks */,
+				F6275F5715AF16260062D479 /* libsicudata.a in Frameworks */,
+				F6275F5815AF16260062D479 /* libsicui18n.a in Frameworks */,
+				F6275F5915AF16260062D479 /* libsicuuc.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		034768DFFF38A50411DB9C8B /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				8DC2EF5B0486A6940098B216 /* HunspellNativeExtension.framework */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		0867D691FE84028FC02AAC07 /* TestNativeExtension */ = {
+			isa = PBXGroup;
+			children = (
+				F6275F6615B40E5C0062D479 /* Utilities.h */,
+				F623A559159CA5DE00A209C5 /* EncConv.cpp */,
+				F623A55A159CA5DE00A209C5 /* EncConv.h */,
+				F674FB6315996E9C00BAB506 /* HunspellNativeExtension.h */,
+				1DBD23391328578300B5B085 /* HunspellNativeExtension.cpp */,
+				08FB77AEFE84172EC02AAC07 /* Classes */,
+				32C88DFF0371C24200C91783 /* Other Sources */,
+				089C1665FE841158C02AAC07 /* Resources */,
+				0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+				034768DFFF38A50411DB9C8B /* Products */,
+			);
+			name = TestNativeExtension;
+			sourceTree = "<group>";
+		};
+		0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+			isa = PBXGroup;
+			children = (
+				F6275F5415AF16260062D479 /* libsicudata.a */,
+				F6275F5515AF16260062D479 /* libsicui18n.a */,
+				F6275F5615AF16260062D479 /* libsicuuc.a */,
+				1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */,
+				1058C7B2FEA5585E11CA2CBB /* Other Frameworks */,
+			);
+			name = "External Frameworks and Libraries";
+			sourceTree = "<group>";
+		};
+		089C1665FE841158C02AAC07 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				8DC2EF5A0486A6940098B216 /* Info.plist */,
+				089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		08FB77AEFE84172EC02AAC07 /* Classes */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Classes;
+			sourceTree = "<group>";
+		};
+		1058C7B0FEA5585E11CA2CBB /* Linked Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1DE3D06F144F354C0007B73C /* Adobe AIR.framework */,
+				1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */,
+			);
+			name = "Linked Frameworks";
+			sourceTree = "<group>";
+		};
+		1058C7B2FEA5585E11CA2CBB /* Other Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				0867D6A5FE840307C02AAC07 /* AppKit.framework */,
+				D2F7E79907B2D74100F64583 /* CoreData.framework */,
+				0867D69BFE84028FC02AAC07 /* Foundation.framework */,
+			);
+			name = "Other Frameworks";
+			sourceTree = "<group>";
+		};
+		32C88DFF0371C24200C91783 /* Other Sources */ = {
+			isa = PBXGroup;
+			children = (
+				32DBCF5E0370ADEE00C91783 /* HunspellNativeExtension_Prefix.pch */,
+			);
+			name = "Other Sources";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		8DC2EF500486A6940098B216 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F674FB6415996E9C00BAB506 /* HunspellNativeExtension.h in Headers */,
+				F623A55C159CA5DE00A209C5 /* EncConv.h in Headers */,
+				F6275F6715B40E5C0062D479 /* Utilities.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		8DC2EF4F0486A6940098B216 /* HunspellNativeExtension */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "HunspellNativeExtension" */;
+			buildPhases = (
+				8DC2EF500486A6940098B216 /* Headers */,
+				8DC2EF520486A6940098B216 /* Resources */,
+				8DC2EF540486A6940098B216 /* Sources */,
+				8DC2EF560486A6940098B216 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = HunspellNativeExtension;
+			productInstallPath = "$(HOME)/Library/Frameworks";
+			productName = TestNativeExtension;
+			productReference = 8DC2EF5B0486A6940098B216 /* HunspellNativeExtension.framework */;
+			productType = "com.apple.product-type.framework";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		0867D690FE84028FC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "HunspellNativeExtension" */;
+			compatibilityVersion = "Xcode 3.1";
+			developmentRegion = English;
+			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+			);
+			mainGroup = 0867D691FE84028FC02AAC07 /* TestNativeExtension */;
+			productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				8DC2EF4F0486A6940098B216 /* HunspellNativeExtension */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		8DC2EF520486A6940098B216 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		8DC2EF540486A6940098B216 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				1DBD233A1328578300B5B085 /* HunspellNativeExtension.cpp in Sources */,
+				F623A55B159CA5DE00A209C5 /* EncConv.cpp in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				089C1667FE841158C02AAC07 /* English */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB91AE08733DA50010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				COPY_PHASE_STRIP = NO;
+				DEAD_CODE_STRIPPING = YES;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXPORTED_SYMBOLS_FILE = Exported_Sym_FIle;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SYSTEM_APPS_DIR)/Adobe Flash Builder 4.6/sdks/4.5.1-air3.0/runtimes/air/mac\"",
+					"\"$(SRCROOT)\"",
+				);
+				FRAMEWORK_VERSION = A;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_FIX_AND_CONTINUE = YES;
+				GCC_MODEL_TUNING = G5;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = HunspellNativeExtension_Prefix.pch;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../third_party/hunspell/src/hunspell,
+					../third_party/agl_tp/agl40/include,
+				);
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Frameworks";
+				LD_DYLIB_INSTALL_NAME = "";
+				LD_GENERATE_MAP_FILE = YES;
+				LD_RUNPATH_SEARCH_PATHS = "@executable_path/../runtimes/air/mac @executable_path/../Frameworks /Library/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"/Library/Frameworks/Adobe\\ AIR.framework/Versions/1.0",
+					"\"$(SRCROOT)/../third_party/agl_tp/agl40/mac32-llvm30-debug/static/lib\"",
+					"\"$(SRCROOT)/../third_party/agl_tp/agl40/data/mac32-llvm30/lilohunspellplugin/static\"",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_CFLAGS = "-fvisibility=hidden";
+				OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
+				OTHER_LDFLAGS = (
+					"-flat_namespace",
+					"-weak_framework",
+					"\"Adobe AIR\"",
+				);
+				PRODUCT_NAME = HunspellNativeExtension;
+				SDKROOT = macosx10.6;
+				STRIP_STYLE = debugging;
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = i386;
+				VERSION_INFO_PREFIX = "_ContextFinalizer\n_ContextInitializer\n_ExtFinalizer\n_ExtInitializer";
+				WRAPPER_EXTENSION = framework;
+			};
+			name = Debug;
+		};
+		1DEB91AF08733DA50010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				COPY_PHASE_STRIP = NO;
+				DEAD_CODE_STRIPPING = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXPORTED_SYMBOLS_FILE = Exported_Sym_FIle;
+				FRAMEWORK_SEARCH_PATHS = (
+					"$(inherited)",
+					"\"$(SYSTEM_APPS_DIR)/Adobe Flash Builder 4.6/sdks/4.5.1-air3.0/runtimes/air/mac\"",
+					"\"$(SRCROOT)\"",
+				);
+				FRAMEWORK_VERSION = A;
+				GCC_MODEL_TUNING = G5;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = HunspellNativeExtension_Prefix.pch;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				HEADER_SEARCH_PATHS = (
+					../third_party/hunspell/src/hunspell,
+					../third_party/agl_tp/agl40/include,
+				);
+				INFOPLIST_FILE = Info.plist;
+				INSTALL_PATH = "$(HOME)/Library/Frameworks";
+				LD_DYLIB_INSTALL_NAME = "";
+				LD_GENERATE_MAP_FILE = YES;
+				LD_RUNPATH_SEARCH_PATHS = "@executable_path/../runtimes/air/mac @executable_path/../Frameworks /Library/Frameworks";
+				LIBRARY_SEARCH_PATHS = (
+					"/Library/Frameworks/Adobe\\ AIR.framework/Versions/1.0",
+					"\"$(SRCROOT)/../third_party/agl_tp/agl40/mac32-llvm30-release/static/lib\"",
+					"\"$(SRCROOT)/../third_party/agl_tp/agl40/data/mac32-llvm30/lilohunspellplugin/static\"",
+				);
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = (
+					"-flat_namespace",
+					"-weak_framework",
+					"\"Adobe AIR\"",
+				);
+				PRODUCT_NAME = HunspellNativeExtension;
+				SDKROOT = macosx10.6;
+				STRIP_STYLE = debugging;
+				USER_HEADER_SEARCH_PATHS = "";
+				VALID_ARCHS = i386;
+				VERSION_INFO_PREFIX = "_ContextFinalizer\n_ContextInitializer\n_ExtFinalizer\n_ExtInitializer";
+				WRAPPER_EXTENSION = framework;
+			};
+			name = Release;
+		};
+		1DEB91B208733DA50010E9CD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					../third_party/hunspell/src/hunspell,
+					../third_party/agl_tp/agl40/include,
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"/Library/Frameworks/Adobe\\ AIR.framework/Versions/1.0",
+				);
+				ONLY_ACTIVE_ARCH = YES;
+				OTHER_LDFLAGS = "";
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Debug;
+		};
+		1DEB91B308733DA50010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				HEADER_SEARCH_PATHS = (
+					../third_party/hunspell/src/hunspell,
+					../third_party/agl_tp/agl40/include,
+				);
+				LIBRARY_SEARCH_PATHS = (
+					"/Library/Frameworks/Adobe\\ AIR.framework/Versions/1.0",
+				);
+				OTHER_LDFLAGS = "";
+				PREBINDING = NO;
+				SDKROOT = macosx10.6;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "HunspellNativeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91AE08733DA50010E9CD /* Debug */,
+				1DEB91AF08733DA50010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "HunspellNativeExtension" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91B208733DA50010E9CD /* Debug */,
+				1DEB91B308733DA50010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..f908177
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/HunspellNativeExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+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.
+
+-->
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:HunspellNativeExtension.xcodeproj">
+   </FileRef>
+</Workspace>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Info.plist
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Info.plist b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Info.plist
new file mode 100644
index 0000000..04103d4
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Info.plist
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+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.
+
+-->
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string></string>
+	<key>CFBundleIdentifier</key>
+	<string>com.yourcompany.${PRODUCT_NAME:rfc1034Identifier}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PRODUCT_NAME}</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>NSPrincipalClass</key>
+	<string></string>
+</dict>
+</plist>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.cpp b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.cpp
new file mode 100644
index 0000000..d2ffb2b
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.cpp
@@ -0,0 +1,20 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.h b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.h
new file mode 100644
index 0000000..d5b5e32
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/Utilities.h
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef HunspellNativeExtension_Utilities_h
+#define HunspellNativeExtension_Utilities_h
+#include <fstream>
+using namespace std;
+bool FileExists(const char * inFilePath)
+    {
+        if(inFilePath == NULL) return false;
+        ifstream file(inFilePath, ios::in);
+        if(file.good())
+        {
+            file.close();
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+
+
+#endif

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/create_fw.sh
----------------------------------------------------------------------
diff --git a/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/create_fw.sh b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/create_fw.sh
new file mode 100644
index 0000000..bedcfa0
--- /dev/null
+++ b/Squiggly/ane/MacFWHunspellANE/HunspellNativeExtension/create_fw.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+################################################################################
+##
+##  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.
+##
+################################################################################
+
+set -x
+
+XCODEBLD="/usr/bin/xcodebuild"
+
+rm -rf ./build
+
+$XCODEBLD -project ./HunspellNativeExtension.xcodeproj	\
+    -configuration Release	\
+    ARCHS="i386"	\
+    clean build
+
+if (( 0 )) ; then
+$XCODEBLD -project ./mac/TestNativeExtension/TestNativeExtension.xcodeproj	\
+    -configuration Release	\
+    ARCHS="i386"	\
+    clean build
+fi
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/README.txt
----------------------------------------------------------------------
diff --git a/Squiggly/ane/README.txt b/Squiggly/ane/README.txt
new file mode 100644
index 0000000..88a7d17
--- /dev/null
+++ b/Squiggly/ane/README.txt
@@ -0,0 +1,28 @@
+How to use the Squiggly SDK
+===================================
+
+Please read the ASDoc first to understand the classes in Squiggly.
+
+If you are using the SpellChecker class directly, you need.
+- AdobeSpellingEngine.swc in [YourProject]/libs folder, you can find it from ./libs
+- Dictionary files in [YourProject]/src folder, your can find them from ./src/dictionaries folder
+
+If you are using the simple UI integration feature (SpellUI class), in addition to what mentioned above, you also need
+- AdobeSpellingConfig.xml in [YourProject]/src
+- AdobeSpellingUI.swc (AdobeSpellingUIEx.swc if you need spark support in Flex 4) in [YourProject]/libs 
+
+This SDK came with English(US) dictionary. You can download additional HunSpell dictionaries, but for now, what we have tested are just English, Spanish, Portuguese, Italian and French. If you are doing this, you need to understand AdobeSpellingConfig.xml.
+
+Here's the content of AdobeSpellingConfig.xml, each entry maps the languageCode with the relative path for resource files. 
+<SpellingConfig>
+  <LanguageResource language="English" languageCode="en_US" ruleFile="dictionaries/en_US/en_US.aff" dictionaryFile="dictionaries/en_US/en_US.dic"/>
+</SpellingConfig>
+
+So if you are adding Spanish, you just need to get the hunspell dictionary es_ES.aff/dic and add one line to your config file.
+  <LanguageResource language="Spanish" languageCode="es_ES" ruleFile="dictionaries/es_ES/es_ES.aff" dictionaryFile="dictionaries/es_ES/es_ES.dic"/>
+
+Note that you can put the dictionaries in another location as long as you update the config file, the config file itself MUST be in [YourProject]/src folder.
+
+
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/build.properties
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/build.properties b/Squiggly/ane/SWCandANE/build.properties
new file mode 100644
index 0000000..78dfaac
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/build.properties
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+
+  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.
+
+-->
+
+#Etc Settings
+TEMP_PASS_CHANGE_THIS=random123$%^
+
+#Certificate for release build.  Modify only when you are making a release build (See RELEASE_GUIDE first)
+STORETYPE=pkcs12
+RELEASE_KEYSTORE_FILE=C:/p/documents/certificates/installapacheflex_self.p12
+CERT_PASSWORD_FILE=C:/p/documents/certificates/squiggly.password
+CERT_NAME=Apache Flex
+CERT_ORG_UNIT=
+CERT_ORG_NAME=
+CERT_COUNTRY=US
+CERT_KEY_TYPE=2048-RSA

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/build.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/build.xml b/Squiggly/ane/SWCandANE/build.xml
new file mode 100644
index 0000000..770b6d5
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/build.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" ?>
+<!--
+
+  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.
+
+-->
+<project default="test" basedir=".">
+
+    <property file="${basedir}/env.properties"/>
+    <property environment="env"/>
+    <property file="${basedir}/local.properties"/>
+    <property file="${basedir}/build.properties"/>
+    <condition property="FLEX_HOME" value="${env.FLEX_HOME}">
+        <isset property="env.FLEX_HOME" />
+    </condition>
+    <condition property="AIR_HOME" value="${env.AIR_HOME}">
+        <isset property="env.AIR_HOME" />
+    </condition>
+
+    <!-- SDK properties -->
+    <property name="FLEX_HOME" value="C:/air3_beta2"/>
+    <property name="AIR_HOME" value="C:/air3_beta2"/>
+	<property name="MXMLC.JAR" value="${FLEX_HOME}/lib/mxmlc.jar"/>
+	<property name="COMPC.JAR" value="${FLEX_HOME}/lib/compc.jar"/>
+	<property name="ADL" value="${AIR_HOME}/bin/adl.exe"/>
+    <property name="ADT.JAR" value="${AIR_HOME}/lib/adt.jar"/>
+
+    <!-- Cert properties -->
+    <condition property="cert_pwd_not_found" >
+		<not>
+       		<available file="${CERT_PASSWORD_FILE}"/>
+		</not>
+    </condition>
+
+	<condition property="KEYSTORE" value="${RELEASE_KEYSTORE_FILE}" >
+		<available file="${CERT_PASSWORD_FILE}"/>
+	</condition>
+
+	<condition property="KEYSTORE" value="${basedir}/temp.p12" >
+		<not>
+			<available file="${CERT_PASSWORD_FILE}"/>
+		</not>
+	</condition>
+
+    <condition property="CERT_PASSWORD" value="${TEMP_PASS_CHANGE_THIS}" >
+		<not>
+       		<available file="${CERT_PASSWORD_FILE}"/>
+		</not>
+    </condition>
+
+    <!-- Project properties -->
+    <property name="STOREPASS" value="${CERT_PASSWORD}" />
+    <property name="APP_ROOT_DIR" value="."/>
+    <property name="APP_NAME" value="HunspellNativeExtensionWorkflow"/>
+    <property name="APP_ROOT_FILE" value="${APP_NAME}.swf"/>
+	<property name="APP_SOURCE_DIR" value="${APP_ROOT_DIR}/src"/>
+    <property name="MAIN_SOURCE" value="${APP_SOURCE_DIR}/${APP_NAME}.mxml"/>
+    <property name="APP_SOURCE_DESCRIPTOR" value="${APP_SOURCE_DIR}/${APP_NAME}-app.xml"/>
+	
+	<!-- Native Extensions -->
+	<property name="NATIVE_EXTENSION_NAME" value="HunspellNativeExtension"/>
+	<property name="NATIVE_EXTENSION_ACTIONSCRIPT_CLASSES" value="com.adobe.linguistics.extensions.HunspellNativeExtension" />
+	<property name="NATIVE_EXTENSION_TMP_DIR" value="${APP_ROOT_DIR}/extensions/tmp"/>
+	<property name="NATIVE_EXTENSION_BIN_DIR" value="${APP_ROOT_DIR}/extensions/bin"/>
+	<property name="NATIVE_EXTENSION_SRC_DIR" value="${APP_ROOT_DIR}/extensions/src"/>
+	<property name="NATIVE_EXTENSION_UNZIPPED_DIR" value="${APP_ROOT_DIR}/extensions/unzipped"/>
+	
+	<!-- Debug settings -->
+    <property name="debug"  location="${APP_ROOT_DIR}/debug"/>
+	<property name="APP_DEBUG_DESCRIPTOR" value="${debug}/${APP_NAME}-app.xml"/>
+    
+     <target name="init" depends="clean">
+     	<mkdir dir="${debug}"/>
+     	<mkdir dir="${NATIVE_EXTENSION_BIN_DIR}"/>
+     	<mkdir dir="${NATIVE_EXTENSION_UNZIPPED_DIR}"/>
+    </target>
+	
+	<target name="compilenativeextensions" depends="init">
+		<mkdir dir="${NATIVE_EXTENSION_TMP_DIR}"/>
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="+configname=air"/>
+			<arg value="-source-path"/>
+			<arg value="src"/>
+			<arg value="-include-classes"/>
+			<arg value="${NATIVE_EXTENSION_ACTIONSCRIPT_CLASSES}"/>
+			<arg value="-external-library-path"/>
+			<arg value="${AIR_HOME}/frameworks/libs/air/airglobal.swc"/>
+			<arg value="-output"/>
+			<arg value="${NATIVE_EXTENSION_TMP_DIR}/nativeextensions.swc"/>
+		</java>
+		<unzip src="${NATIVE_EXTENSION_TMP_DIR}/nativeextensions.swc" dest="${NATIVE_EXTENSION_TMP_DIR}" />
+	</target>
+	
+	<target name="packagenativeextensions" depends="compilenativeextensions">
+		<!-- dll files -->
+		<pathconvert property="nativeExtensionFiles" pathsep="' '" dirsep="/">
+			<path>
+				<fileset dir="${NATIVE_EXTENSION_SRC_DIR}" includes="**/*.dll"/>
+			</path>
+			<chainedmapper>
+				<flattenmapper/>
+			</chainedmapper>
+		</pathconvert>
+		<echo>native extension files: ${nativeExtensionFiles}</echo>
+		<!-- flatten directory -->
+		<copy todir="${NATIVE_EXTENSION_TMP_DIR}" flatten="true">
+			<fileset dir="${NATIVE_EXTENSION_SRC_DIR}" />
+		</copy>
+        <echo>${STOREPASS}</echo>
+        <echo>${KEYSTORE}</echo>
+		 <java jar="${ADT.JAR}" fork="true" dir="${NATIVE_EXTENSION_TMP_DIR}" failonerror="true">
+		 	<arg value="-package"/>
+		 	<arg value="-storetype"/>
+		 	<arg value="pkcs12"/>
+		 	<arg value="-storepass"/>
+		 	<arg value="${STOREPASS}"/>
+		 	<arg value="-keystore"/>
+		 	<arg value="${KEYSTORE}"/>
+		 	<arg value="-tsa"/>
+		 	<arg value="none"/>
+		 	<arg value="-target"/>
+		 	<arg value="ane"/>
+		 	<arg value="${NATIVE_EXTENSION_NAME}.ane"/>
+		 	<arg value="extension.xml"/>
+		 	<arg value="-swc"/>
+		 	<arg value="nativeextensions.swc"/>
+		 	<arg value="-platform"/>
+		 	<arg value="Windows-x86"/>
+		 	<arg value="library.swf"/>
+		 	<arg line="'${nativeExtensionFiles}'" />
+		 </java>
+		<copy file="${NATIVE_EXTENSION_TMP_DIR}/${NATIVE_EXTENSION_NAME}.ane" tofile="${NATIVE_EXTENSION_BIN_DIR}/${NATIVE_EXTENSION_NAME}.ane" />
+		<delete dir="${NATIVE_EXTENSION_TMP_DIR}"/>
+	</target>
+	
+	<target name="unpacknativeextensions" depends="packagenativeextensions">
+		<unzip src="${NATIVE_EXTENSION_BIN_DIR}/${NATIVE_EXTENSION_NAME}.ane" dest="${NATIVE_EXTENSION_UNZIPPED_DIR}/${NATIVE_EXTENSION_NAME}.ane" />
+	</target>
+
+    <target name="debugcompile" depends="unpacknativeextensions">
+        <java jar="${MXMLC.JAR}" fork="true" failonerror="true">
+            <arg value="-debug=true"/>
+            <arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+            <arg value="+configname=air"/>
+            <arg value="-file-specs=${MAIN_SOURCE}"/>
+            <arg value="-output=${debug}/${APP_ROOT_FILE}"/>
+        </java>
+    	<copy filtering="true" file="${APP_SOURCE_DESCRIPTOR}" tofile="${APP_DEBUG_DESCRIPTOR}" />
+    	<replace file="${APP_DEBUG_DESCRIPTOR}">
+    		<replacefilter token="[This value will be overwritten by Flash Builder in the output app.xml]" value="${APP_ROOT_FILE}"/>
+    	</replace>
+    </target>
+
+    <target name="test" depends="certificate,debugcompile">
+        <exec executable="${ADL}">
+            <arg value="${APP_DEBUG_DESCRIPTOR}"/>
+			<arg value="-extdir"/>
+			<arg value="${NATIVE_EXTENSION_UNZIPPED_DIR}" />
+            <arg value="${debug}"/>
+          </exec> 
+    </target>
+
+    <!-- Make sure to use the same certificate each time so we can update the app. -->
+    <target name="certificate" if="cert_pwd_not_found">
+        <antcall target="generate-certificate"/>
+    </target>
+
+    <target name="generate-certificate">
+    	<echo message="Using cert ${KEYSTORE}" />
+        <java jar="${ADT.JAR}" fork="true"
+            failonerror="true">
+            <arg value="-certificate"/>
+            <arg value="-cn"/>
+            <arg value="${CERT_NAME}"/>
+            <arg value="-ou"/>
+            <arg value="${CERT_ORG_UNIT}"/>
+            <arg value="-o"/>
+            <arg value="${CERT_ORG_NAME}"/>
+            <arg value="-c"/>
+            <arg value="${CERT_COUNTRY}"/>
+            <arg value="${CERT_KEY_TYPE}"/>
+            <arg value="${KEYSTORE}"/>
+            <arg value="${CERT_PASSWORD}"/>
+        </java>
+    </target>
+    
+    <target name="clean" description="clean up">
+    	<delete dir="${debug}"/>
+    	<delete file="${basedir}/temp.p12"/>
+    	<delete dir="${NATIVE_EXTENSION_BIN_DIR}"/>
+    	<delete dir="${NATIVE_EXTENSION_TMP_DIR}"/>
+    	<delete dir="${NATIVE_EXTENSION_UNZIPPED_DIR}"/>
+    </target>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/create_ane.sh
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/create_ane.sh b/Squiggly/ane/SWCandANE/create_ane.sh
new file mode 100644
index 0000000..0e495b0
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/create_ane.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+################################################################################
+##
+##  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.
+##
+################################################################################
+
+set -x
+
+FLEX_SDK=/Applications/Adobe\ Flash\ Builder\ 4.6/sdks/4.5.1-air3.0
+
+if [[ $# = 1 ]] ; then 
+    FLEX_SDK="$1"
+fi 
+
+JAR="/usr/bin/jar"
+
+PASS=adobe	# Others used: none, test
+
+rm -rf extensions/src/assets
+rm -f HunspellNativeExtension.ane
+
+mkdir -p extensions/src/assets
+cp "./HunspellNativeExtension.swc" extensions/src/assets
+
+mkdir -p extensions/src/assets/swc-contents
+pushd extensions/src/assets/swc-contents
+$JAR xf ../HunspellNativeExtension.swc catalog.xml library.swf
+popd
+
+mkdir -p extensions/src/assets/platform
+mkdir -p extensions/src/assets/platform/mac
+mkdir -p extensions/src/assets/platform/windows
+
+cp -R "../MacFWHunspellANE/HunspellNativeExtension/build/Release/HunspellNativeExtension.framework"	\
+    extensions/src/assets/platform/mac
+cp -f "./extensions/src/windows/HunspellNativeExtension.dll"	\
+extensions/src/assets/platform/windows
+cp extensions/src/assets/swc-contents/library.swf extensions/src/assets/platform/mac
+cp extensions/src/assets/swc-contents/library.swf extensions/src/assets/platform/windows
+cp "./AdobeGtlibTeam.p12" extensions/src/assets/AdobeGtlibTeam.p12
+echo "testing"
+echo
+ls -l "$FLEX_SDK"/lib/adt.jar
+echo
+
+"$FLEX_SDK"/bin/adt -package	\
+    -storetype PKCS12 -keystore extensions/src/assets/AdobeGtlibTeam.p12 -storepass $PASS	\
+    -target ane HunspellNativeExtension.ane extensions/src/extension.xml	\
+    -swc HunspellNativeExtension.swc	\
+    -platform Windows-x86 -C extensions/src/assets/platform/windows/ library.swf   \
+    HunspellNativeExtension.dll    \
+    -platform MacOS-x86	\
+    -C extensions/src/assets/platform/mac .
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/create_swc.sh
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/create_swc.sh b/Squiggly/ane/SWCandANE/create_swc.sh
new file mode 100644
index 0000000..bbcdfbe
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/create_swc.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+################################################################################
+##
+##  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.
+##
+################################################################################
+
+set -x
+
+# Set FLEX_SDK env var to a flex sdk with a serrano air overlay
+
+FLEX_SDK=/Applications/Adobe\ Flash\ Builder\ 4.6/sdks/4.5.1-air3.0
+if [[ $# = 1 ]] ; then 
+    FLEX_SDK="$1"
+fi 
+
+rm -f HunspellNativeExtension.swc
+
+"$FLEX_SDK"/bin/acompc -target-player=13	\
+    -source-path src	\
+    -include-classes	\
+    com.adobe.linguistics.extensions.HunspellNativeExtension	\
+    -output=HunspellNativeExtension.swc
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/extensions/src/extension.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/extensions/src/extension.xml b/Squiggly/ane/SWCandANE/extensions/src/extension.xml
new file mode 100644
index 0000000..bd09460
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/extensions/src/extension.xml
@@ -0,0 +1,38 @@
+<!--
+
+  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.
+
+-->
+<extension xmlns="http://ns.adobe.com/air/extension/2.5">
+    <id>com.adobe.linguistics.extensions.HunspellNativeExtension</id>
+    <versionNumber>1.0.0</versionNumber>
+    <platforms>
+        <platform name="MacOS-x86">
+            <applicationDeployment>
+                <nativeLibrary>HunspellNativeExtension.framework</nativeLibrary>
+                <initializer>ExtInitializer</initializer>
+                <finalizer>ExtFinalizer</finalizer>
+            </applicationDeployment>
+        </platform>
+        <platform name="Windows-x86">
+            <applicationDeployment>
+                <nativeLibrary>HunspellNativeExtension.dll</nativeLibrary>
+                <initializer>ExtInitializer</initializer>
+                <finalizer>ExtFinalizer</finalizer>
+            </applicationDeployment>
+        </platform>
+    </platforms>
+</extension>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow-app.xml b/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow-app.xml
new file mode 100644
index 0000000..5c13ad9
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow-app.xml
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!--
+
+  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.
+
+-->
+<application xmlns="http://ns.adobe.com/air/application/3.1">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/3.0
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<extensions>
+		<extensionID>com.adobe.linguistics.extensions.HunspellNativeExtension</extensionID>
+	</extensions>
+
+	<!-- A universally unique application identifier. Must be unique across all AIR applications.
+	Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
+	<id>HunspellNativeExtensionWorkflow</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>HunspellNativeExtensionWorkflow</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>HunspellNativeExtensionWorkflow</name>
+	
+	<!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. 
+	Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
+	An updated version of application must have a versionNumber value higher than the previous version. Required for namespace >= 2.5 . -->
+	<versionNumber>0.0.0</versionNumber>
+		         
+	<!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. -->
+	<!-- <versionLabel></versionLabel> -->
+
+	<!-- Description, displayed in the AIR application installer.
+	May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 -->
+	<!-- <publisherID></publisherID> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flash Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flash Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width in pixels. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height in pixels. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair in pixels, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair in pixels, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+
+        <!-- The initial aspect ratio of the app when launched (either "portrait" or "landscape"). Optional. Mobile only. Default is the natural orientation of the device -->
+
+        <!-- <aspectRatio></aspectRatio> -->
+
+        <!-- Whether the app will begin auto-orienting on launch. Optional. Mobile only. Default false -->
+
+        <!-- <autoOrients></autoOrients> -->
+
+        <!-- Whether the app launches in full screen. Optional. Mobile only. Default false -->
+
+        <!-- <fullScreen></fullScreen> -->
+
+        <!-- The render mode for the app (either auto, cpu, or gpu). Optional. Mobile only. Default auto -->
+
+        <!-- <renderMode></renderMode> -->
+
+		<!-- Whether or not to pan when a soft keyboard is raised or lowered (either "pan" or "none").  Optional.  Defaults "pan." -->
+		<!-- <softKeyboardBehavior></softKeyboardBehavior> -->
+	<autoOrients>false</autoOrients>
+        <fullScreen>false</fullScreen>
+        <visible>false</visible>
+    </initialWindow>
+
+	<!-- We recommend omitting the supportedProfiles element, -->
+	<!-- which in turn permits your application to be deployed to all -->
+	<!-- devices supported by AIR. If you wish to restrict deployment -->
+	<!-- (i.e., to only mobile devices) then add this element and list -->
+	<!-- only the profiles which your application does support. -->
+	<supportedProfiles>extendedDesktop</supportedProfiles>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+	specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image36x36></image36x36>
+		<image48x48></image48x48>
+		<image57x57></image57x57>
+		<image72x72></image72x72>
+		<image114x114></image114x114>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+    <!-- iOS specific capabilities -->
+	<!-- <iPhone> -->
+		<!-- A list of plist key/value pairs to be added to the application Info.plist -->
+		<!-- <InfoAdditions>
+            <![CDATA[
+                <key>UIDeviceFamily</key>
+                <array>
+                    <string>1</string>
+                    <string>2</string>
+                </array>
+                <key>UIStatusBarStyle</key>
+                <string>UIStatusBarStyleBlackOpaque</string>
+                <key>UIRequiresPersistentWiFi</key>
+                <string>YES</string>
+            ]]>
+        </InfoAdditions> -->
+	<!-- Display Resolution for the app (either "standard" or "high"). Optional. Default "standard" -->
+	<!-- <requestedDisplayResolution></requestedDisplayResolution> -->
+	<!-- </iPhone> -->
+
+	<!-- Specify Android specific tags that get passed to AndroidManifest.xml file. -->
+    <!--<android> -->
+    <!--	<manifestAdditions>
+		<![CDATA[
+			<manifest android:installLocation="auto">
+				<uses-permission android:name="android.permission.INTERNET"/>
+				<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+				<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+				<uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/>
+				<application android:enabled="true">
+					<activity android:excludeFromRecents="false">
+						<intent-filter>
+							<action android:name="android.intent.action.MAIN"/>
+							<category android:name="android.intent.category.LAUNCHER"/>
+						</intent-filter>
+					</activity>
+				</application>
+            </manifest>
+		]]>
+        </manifestAdditions> -->
+	    <!-- Color depth for the app (either "32bit" or "16bit"). Optional. Default 16bit before namespace 3.0, 32bit after -->
+        <!-- <colorDepth></colorDepth> -->
+    <!-- </android> -->
+	<!-- End of the schema for adding the android specific tags in AndroidManifest.xml file -->
+
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow.mxml b/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow.mxml
new file mode 100644
index 0000000..d251e9e
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/src/HunspellNativeExtensionWorkflow.mxml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
+					   xmlns:s="library://ns.adobe.com/flex/spark" 
+					   xmlns:mx="library://ns.adobe.com/flex/mx"
+					   >
+	<s:layout>
+		<s:VerticalLayout paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"/>
+	</s:layout>
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.extensions.HunspellNativeExtension;
+			
+			import mx.events.FlexEvent;
+			
+			private static const HUNSPELL_INIT_FAIL:int= -1
+			private static const RESOURCE_FILES_MISSING:int= -2
+			private static const HUNSPELL_INIT_SUCCESS:int= 1
+				
+			private var ext:HunspellNativeExtension;
+			private var isInit:Boolean;
+			private var locale:String;
+			private var dicPath:String;
+			protected function initHandler(event:Event):void
+			{
+				locale=localeInput.text;
+				trace(locale);
+				dicPath="C:\\Program Files\\Common Files\\adobe\\linguistics\\Museüß";
+				trace(dicPath);
+				initInputs.text="Entered lnguage="+locale+" Dictionary Path: "+dicPath;
+				ext = new HunspellNativeExtension();
+				var result:int=ext.initHunspellObject(locale, dicPath);
+				trace(result);
+				if(result==HUNSPELL_INIT_SUCCESS)
+				{
+					isInit=true;
+				}
+				else
+					{
+					isInit=false;
+					if(result==RESOURCE_FILES_MISSING) trace("RESOURCE_FILES_MISSING");
+					if(result==HUNSPELL_INIT_FAIL) trace("HUNSPELL_INIT_FAIL");
+					}
+				trace("application complete");
+			}
+			
+			protected function deInitHandler(event:Event):void{
+				ext.deInitHunspellNativeExtension();
+				ext=null;
+				initInputs.text="Hunspell Native Extension Disposed";
+			}
+			protected function talkBack(event:Event):void
+			{
+				if(isInit)
+				{
+				talkb.text= ext.talkBack(inputField.text);
+				}
+				else
+				{
+					talkb.text= "Not Inited";
+				}
+			}
+			
+			protected function clickHandler(event:MouseEvent):void
+			{
+				suggestionsField.text="";
+				if(isInit)
+				{
+					if(ext.checkWord(inputField.text, locale)==0)
+					{
+						outputField.text = "false"; 
+						var suggArray:Array=ext.getSuggestions(inputField.text, locale);
+						for each (var sugg:String in suggArray)
+						suggestionsField.text += "\n"+ sugg;
+					}
+					else
+					{
+						outputField.text = "true"; 
+					}
+				}
+				else
+					outputField.text = " Error";
+				trace("click handler");
+			}
+			
+		]]>
+	</fx:Script>
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<s:Label text="Enter Language: "/>
+	<s:TextInput text="de_DE" id="localeInput" width="119"/>
+	<s:HGroup>
+		<s:Button width="20%" label="Init application" click="initHandler(event)"/>
+		<s:Button width="20%" label="De-Init application" click="deInitHandler(event)"/>	
+	</s:HGroup>
+	<s:Label id="initInputs"/>
+	<s:Label text="Enter Word:"/>
+	<s:TextInput id="inputField" width="50%"/>
+	<s:Button label="Talk back" width="20%" click="talkBack(event)"/>
+	<s:Label id="talkb" text="Label"/>
+	<s:Button width="20%" label="Check Word" click="clickHandler(event)"/>
+	<s:Label text="Output:"/>
+	<s:TextInput id="outputField" width="50%"/>
+	<s:TextArea id="suggestionsField" />
+</s:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/SWCandANE/src/com/adobe/linguistics/extensions/HunspellNativeExtension.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/SWCandANE/src/com/adobe/linguistics/extensions/HunspellNativeExtension.as b/Squiggly/ane/SWCandANE/src/com/adobe/linguistics/extensions/HunspellNativeExtension.as
new file mode 100644
index 0000000..8303ec7
--- /dev/null
+++ b/Squiggly/ane/SWCandANE/src/com/adobe/linguistics/extensions/HunspellNativeExtension.as
@@ -0,0 +1,128 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.extensions
+{
+	import flash.events.EventDispatcher;
+	import flash.external.ExtensionContext;
+
+	
+	public class HunspellNativeExtension extends EventDispatcher
+	{
+		
+		private static var isInstantiated:Boolean = false;
+		private static var context:ExtensionContext;
+		
+		private static const HUNSPELL_INIT_FAIL:int= -1
+		private static const RESOURCE_FILES_MISSING:int= -2
+		private static const HUNSPELL_INIT_SUCCESS:int= 1
+		
+		/**
+		 * Initialize the Hunspell Native Extension
+		 * 
+		 * @playerversion Flash 11.1
+		 * @langversion 3.0
+		 */
+		
+		public function HunspellNativeExtension()
+		{
+			super();
+			
+			if (isInstantiated)
+				return;
+			
+			try
+			{
+				context = ExtensionContext.createExtensionContext("com.adobe.linguistics.extensions.HunspellNativeExtension", ""); 
+				isInstantiated = true;
+			}
+			catch (e:Error)
+			{
+			}
+		}
+		
+		public function talkBack(message:String):*
+		{
+			
+			return context.call("talkBack", message);
+		}
+		
+		/**
+		 * Initialize the Hunspell Object of ANE
+		 * 
+		 * @param locale The locale <code>String</code> for which spell checker is constructed. eg: "en_US"
+		 * @param dictionaryPath The URL <code>String</code> specifying the third party resource location 
+		 * @return <code>int</code> value. HUNSPELL_INIT_SUCCESS for success. HUNSPELL_INIT_FAIL, RESOURCE_FILES_MISSING for error. 
+		 * @playerversion Flash 11.1
+		 * @langversion 3.0
+		 */
+		
+		public function initHunspellObject(locale:String, dictionaryPath:String):int
+		{
+			var rv:int=context.call("initHunspellObject", locale, dictionaryPath) as int;
+			//trace(rv);
+			return rv;
+		}
+
+		/**
+		 * Check the input word. Return true or false depending on whether the word is correct or incorrect.
+		 * 
+		 * @param inpWord The input word <code>String</code>.
+		 * @param locale The locale <code>String</code> for which spell checker is constructed. eg: "en_US"
+		 * @return <code>Boolean</code> value. <code>True</code> for correct word. <code>False</code> for incorrect. 
+		 * @playerversion Flash 11.1
+		 * @langversion 3.0
+		 */
+		
+		public function checkWord(inpWord:String, locale:String):Boolean
+		{
+			var rv:int=1;
+			rv= context.call("checkWord", inpWord, locale) as int;
+			return (rv?true:false);
+		}
+		
+		/**
+		 * Return an <code>Array</code> of suggestions for input word. 
+		 * 
+		 * @param inpWord The input word <code>String</code>.
+		 * @param locale The locale <code>String</code> for which spell checker is constructed. eg: "en_US"
+		 * @return <code>Array</code> of suggestions. Returns null array for correct word.
+		 * @playerversion Flash 11.1
+		 * @langversion 3.0
+		 */
+		public function getSuggestions(inpWord:String, locale:String):Array
+		{	
+			return context.call("getSuggestions", inpWord, locale) as Array;
+		}
+		
+		/**
+		 * A de-initialize function which disposes the loaded ANE.
+		 * 
+		 * @playerversion Flash 11.1
+		 * @langversion 3.0
+		 */
+		
+		public function deInitHunspellNativeExtension():void
+		{
+			if(!isInstantiated) return;
+			isInstantiated=false;
+			return context.dispose();
+		}
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
new file mode 100644
index 0000000..a01751a
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
@@ -0,0 +1,82 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*************************************************************************
+* Author:			Zhigang Qi(zqi@adobe.com)
+* 					Xie Fang(xfang@adobe.com)
+* Created:			06/02/2008
+**************************************************************************/
+
+/* 
+* ToDo: Create ASDoc style comment to generate the API document.
+*/
+package com.adobe.linguistics.utils
+{
+	/**
+	 * The <code>ITokenizer</code> Interface.
+	 * This interface defines default methods which will be used for Adobe Linguistic Service.
+	 * Be independent from any UI component or be able to adapt to a given UI component. 
+	 * Provide or define standardized way so that third-party can switch to their tokenizer.
+	 * Be able to use for any given language either by some kind of language specific handling or by some kind of unified logic for any given language.
+	 * More sophisticated implementations can be done for particular locales or environments in an application by implementing this interface.
+
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public interface ITokenizer
+	{
+		
+		/**
+		 * Return the first word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getFirstToken():Token;
+		
+		/**
+		 * Return the last word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getLastToken():Token;
+		
+		/**
+		 * Determine the next word following the current token.  
+		 * 
+		 * Return the token of the next word or <code>lastToken</code> object if all word have been returned.
+		 * @param token A <code>Token</code> object to be used for determining next word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getNextToken(token:Token):Token;
+		
+		/**
+		 * Determine the previous word preceding the current token.  
+		 * 
+		 * Return the token of the previous word or <code>firstToken</code> object if all word have been returned.
+		 * @param token A <code>Token</code> object to be used for determining previous word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getPreviousToken(token:Token):Token;
+
+	}
+}
\ No newline at end of file


[05/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellUI.as
new file mode 100644
index 0000000..426ca4c
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
new file mode 100644
index 0000000..d84f325
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
new file mode 100644
index 0000000..91b0d5f
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
new file mode 100644
index 0000000..9c05b3b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
new file mode 100644
index 0000000..3b5a309
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
new file mode 100644
index 0000000..8196691
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
new file mode 100644
index 0000000..ffe9653
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
new file mode 100644
index 0000000..3ae7a88
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
new file mode 100644
index 0000000..27cd2fb
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
new file mode 100644
index 0000000..92b7c71
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as b/Squiggly/main/AdobeSpellingUI/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
new file mode 100644
index 0000000..749e218
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUI/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/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloHighlighter.as
new file mode 100644
index 0000000..28f16e6
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/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


[09/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as
new file mode 100644
index 0000000..f792b5d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as
@@ -0,0 +1,1026 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.rule.PrefixEntry;
+	import com.adobe.linguistics.spelling.core.rule.SuffixEntry;
+	import com.adobe.linguistics.spelling.core.utils.*;
+	
+	import flash.utils.Dictionary;
+	import flash.utils.getTimer;
+	
+	public class SuggestionManager
+	{
+		
+		private var _attributeMgr:LinguisticRule;
+		private var _maxSug:int;
+		private var _languageCode:String;
+		private var _ckey:String;
+		private var _cUpperTry:String;
+		private var _cLowerTry:String;
+		private var _cAllTry:String;
+		private var _maxngramsugs:int;
+		private var _fastMode:Boolean;
+		
+		private var _word:String;
+		private var _guessSuggestions:SuggestionsResult;
+		private var _guessWordList:SuggestionsResult;
+		private var guess:Array = new Array (InternalConstants.MAX_GUESS);
+		private var gscore:Array = new Array ( InternalConstants.MAX_GUESS);
+		
+		public function SuggestionManager( attrMgr:LinguisticRule, fastMode:Boolean = true )
+		{
+			this._maxSug = InternalConstants.MAXSUGGESTION;
+			this._attributeMgr = attrMgr;
+			this._ckey = this._attributeMgr.keyString;
+
+			this._cAllTry  = this._attributeMgr.tryString;
+			this._cUpperTry = "";
+			this._cLowerTry = ""; // lower and netual...
+			for ( var i:int = 0; (this._attributeMgr.tryString != null)&&(i < this._attributeMgr.tryString.length); ++i ) {
+				if ( this._attributeMgr.tryString.charAt(i) == this._attributeMgr.tryString.charAt(i).toLocaleLowerCase() ) {
+					this._cLowerTry+=this._attributeMgr.tryString.charAt(i);
+				} else {
+					this._cUpperTry+= this._attributeMgr.tryString.charAt(i);
+				}
+				
+			}
+
+			this._maxngramsugs = InternalConstants.MAXNGRAMSUGS;
+			this._fastMode = fastMode;
+			
+			//initialized viriable for performance...
+			_word=null;
+			_guessSuggestions = new SuggestionsResult(InternalConstants.MAX_ROOTS, compareSuggestion );
+			_guessWordList = new SuggestionsResult( InternalConstants.MAX_GUESS, compareSuggestion );
+			if ( this._attributeMgr.maxNgramSuggestions > 0 ) this._maxngramsugs = this._attributeMgr.maxNgramSuggestions;
+		}
+		
+		public function get fastMode():Boolean {
+			return this._fastMode;
+		}
+		
+		public function set fastMode( value:Boolean ) :void {
+			this._fastMode = value;
+		}
+		
+		private static function compareSuggestion( obj1:*, obj2:*):int {
+			return (obj1.score-obj2.score);
+		}
+		
+		
+		public function set languageCode(value:String) :void {
+			this._languageCode = value;	
+		}
+		
+		public function get languageCode():String {
+			return this._languageCode;
+		}
+		
+		public function nsuggest( result:Array, word:String ):int {
+
+			if ( !((result.length+this._maxngramsugs) <= this._maxSug) ) return result.length;
+
+
+			var nsug:int = result.length;
+			var i:int,j:int,sc:int, opt:int, n:int = word.length;
+			var arr:Array;
+			var sd:SquigglyDictionary;
+			var dict:Dictionary;
+			_word = word;
+			var initCap:Boolean = (word.charAt(0) == word.charAt(0).toLocaleLowerCase() )? false:true;
+			var wordCapValue:int = word.charAt(0).toLocaleUpperCase().charCodeAt(0);
+			_guessSuggestions.clear();
+			
+			/* A filter based on string length, it could be */
+			var rangeOffset:int =5;
+			var endRange:int = word.length + (rangeOffset-2);
+			var startRange:int =  (word.length>(rangeOffset+2)) ? (word.length-rangeOffset):2  ;
+	
+					var counter:Number=0
+					var startTime:Number = getTimer();
+
+			// exhaustively search through all root words
+			// keeping track of the MAX_ROOTS most similar root words
+			
+			// word reversing wrapper for complex prefixes
+			
+			// set character based ngram suggestion for words with non-BMP Unicode characters
+			
+			//a filter for performance improvement...
+			var firstCodeValue:Number =word.charCodeAt(0), lastCodeValue:Number = word.charCodeAt(word.length-1);
+			
+			
+			for ( i=0;i<this._attributeMgr.dictionaryManager.dictonaryList.length; ++i ) {
+				sd = this._attributeMgr.dictionaryManager.dictonaryList[i];
+				dict = sd.dictionary;
+				
+				var lowerS:String;
+				var he:HashEntry;
+				opt = InternalConstants.NGRAM_LONGER_WORSE + InternalConstants.NGRAM_LOWERING;
+				for( var key:String in dict ) {
+					if ( (key.length < startRange) || (key.length > endRange) ) continue;
+					if ( (this._fastMode) && (firstCodeValue != key.charCodeAt(0)) && (lastCodeValue != key.charCodeAt(key.length-1)) ) continue;
+					counter++;
+
+					sc = ngram( 3, _word,key,opt) + leftCommonSubString(_word, key, initCap, wordCapValue);
+					
+					if ( sc > 0  ) {
+						if ( _guessSuggestions.size < InternalConstants.MAX_ROOTS ) {
+							if ( dict[key].affixFlagVector && 
+								(dict[key].testAffix( this._attributeMgr.forbiddenWord ) ||
+								dict[key].testAffix( this._attributeMgr.onlyInCompound) ||
+								dict[key].testAffix( this._attributeMgr.noSuggest ) ||
+								dict[key].testAffix( InternalConstants.ONLYUPCASEFLAG )
+								)) continue; 
+							_guessSuggestions.insert( new SuggestionEntry(sc,key, dict[key] ) );
+							if ( _guessSuggestions.size == InternalConstants.MAX_ROOTS ) {
+								_guessSuggestions.buildheap();
+							}
+						}else {
+							if ( sc > _guessSuggestions.front.score ) {
+								_guessSuggestions.front.score = sc;
+								_guessSuggestions.front.key =  key;
+								_guessSuggestions.front.hashEntry = dict[key];
+								_guessSuggestions.updateFront();
+							}
+						}
+					}
+				}
+			}
+			
+			var thresh:int = 0;
+			var mw:String;
+			for ( var sp:int = 1; sp < 4; ++sp) {
+				mw = word;
+				for ( var k:int=sp; k<n; k+=4) {
+					mw = mw.substring(0,k) + "*" + mw.substring(k+1);
+				}
+				thresh = thresh + ngram( n, word, mw, InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING);
+			}
+			thresh = thresh /3;
+			thresh --;
+
+			// now expand affixes on each of these root words and
+			// and use length adjusted ngram scores to select
+			// possible suggestions
+			_guessWordList.clear();
+
+
+			//work arround for inconsitent ordered Dictionary table. bof
+			if ( _guessSuggestions.isEmpty() ) return result.length;
+			var lowestScore:int = _guessSuggestions.front.score;
+			var indexArr:Array;
+			if ( _guessSuggestions.size != _guessSuggestions.maxSize ){
+				indexArr=_guessSuggestions.data.slice(0,_guessSuggestions.size).sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY);
+			}else{
+				indexArr=_guessSuggestions.data.sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY);
+			}
+			//work arround for inconsitent ordered Dictionary table. bof
+
+			// root list;
+			for each ( i in indexArr ) {
+				//work arround for inconsitent ordered Dictionary table. bof
+				if ( i==0 || _guessSuggestions.data[i].score == lowestScore ) continue;
+				//work arround for inconsitent ordered Dictionary table. bof
+				
+				var candList:Array = new Array();
+				var candOriginalList:Array = new Array();
+				expandRootWord(candList,candOriginalList, InternalConstants.MAX_WORDS, _guessSuggestions.data[i].key, _guessSuggestions.data[i].hashEntry, word );
+				for ( j=0; j < candList.length; ++j) {
+					sc = ngram ( n, word, candList[j], InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING) + leftCommonSubString(word, candList[j],initCap, wordCapValue);
+					if ( (sc>thresh) ) {
+						if ( _guessWordList.size < InternalConstants.MAX_GUESS ) {
+							_guessWordList.insert( new GuessWord(sc,candList[j], null ) );
+							if ( _guessWordList.size == InternalConstants.MAX_GUESS ) {
+								_guessWordList.buildheap();
+							}
+						}else {
+							if ( sc > _guessWordList.front.score ) {
+								_guessWordList.front.score = sc;
+								_guessWordList.front.key =  candList[j];
+								_guessWordList.front.original = null;
+								_guessWordList.updateFront();
+							}
+						}
+						
+					}
+				}
+			}
+
+			// now we are done generating guesses
+			// sort in order of decreasing score
+			var guessArr:Array = _guessWordList.toArray().sortOn("score",Array.NUMERIC | Array.DESCENDING);
+
+
+			// weight suggestions with a similarity index, based on
+			// the longest common subsequent algorithm and resort
+			var refobj:RefObject = new RefObject(0);
+			var gl:String;
+			for ( i=guessArr.length-1;i>= 0; --i ) {
+				gl = guessArr[i].key.toLocaleLowerCase();
+				var _lcs:int = StringUtils.lcslen(word, gl);
+				// same characters with different casing
+				if ( (n==gl.length) && (n == _lcs) ) {
+					guessArr[i].score += 2000;
+					break;
+				}
+				// heuristic weigthing of ngram scores
+				guessArr[i].score += 
+					// length of longest common subsequent minus length difference
+					2 * _lcs - Math.abs((int) (n - guessArr[i].key.length)) +
+					// weight length of the left common substring
+					leftCommonSubString(word, gl,initCap, wordCapValue) +
+					// weight equal character positions
+					((_lcs == StringUtils.commonCharacterPositions(word, gl, refobj)) ? 1: 0) +
+					// swap character (not neighboring)
+					((refobj.ref) ? 1000 : 0);
+			}
+
+			guessArr = guessArr.sortOn("score", Array.NUMERIC | Array.DESCENDING);
+			
+			
+			// copy over
+			var oldnsug:int = nsug;
+			var same:int = 0;
+			for ( i=0;i< guessArr.length; ++i ) {
+				if ( (nsug < this._maxSug) && (result.length < (oldnsug + this._maxngramsugs)) && (!same || (guessArr[i].score > 1000)) ) {
+					var unique:int = 1;
+					// leave only excellent suggestions, if exists
+					if ( guessArr[i].score > 1000 ) same = 1;
+					// don't suggest previous suggestions or a previous suggestion with prefixes or affixes
+					for ( j=0;j< result.length; ++j) {
+						if ( ( guessArr[i].key.indexOf(result[j]) != -1) || !checkWord(guessArr[i].key) ) unique = 0;
+					}
+					if ( unique ) {
+						result.push( guessArr[i].key );
+					}
+				}
+				
+			}
+			
+					var endTime:Number = getTimer();
+			return nsug;
+		}
+		
+		private function testValidSuggestion(element:*, gw:GuessWord):Boolean {
+			if ( gw.key.indexOf( element ) ) 
+				return false;
+			if ( !checkWord(element) ) return false; 
+			return true;
+		}
+
+		private function expandRootWord(guessWordList:Array, guessOriginalList:Array, maxn:int, root:String, he:HashEntry, badWord:String) :void {
+			// first add root word to list
+			var nh:int = 0, i:int, j:int;
+			var sfx:SuffixEntry;
+			var pfx:PrefixEntry;
+			var newWord:String;
+			var crossFlagArray:Array = new Array();
+			if ( (guessWordList.length < maxn) && 
+			!( (he.affixFlagVector != null) &&
+			( (this._attributeMgr.needAffix && he.testAffix(this._attributeMgr.needAffix)) || ( this._attributeMgr.onlyInCompound && he.testAffix(this._attributeMgr.onlyInCompound))))
+			){
+				guessWordList[nh] = root;
+				guessOriginalList[nh] = root;
+				crossFlagArray[nh] = false;
+				nh++;
+			}
+			
+			// handle suffixes
+			for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
+				sfx= this._attributeMgr.suffixFlagTable[he.affixFlagVector.charAt(i)];
+				while( sfx  ) {
+					var index:int = badWord.lastIndexOf(sfx.affixKey);
+					if ( (index != -1) && ( index== (badWord.length-sfx.affixKey.length)) ) {
+						newWord = sfx.add(root);
+						if ( newWord) {
+							guessWordList[nh] = newWord;
+							guessOriginalList[nh] = root;
+							crossFlagArray[nh] = sfx.permissionToCombine;
+							nh++;
+						}
+					}
+					sfx = sfx.nextElementWithFlag; 
+				}
+			}
+			
+			// handle cross products of prefixes and suffixes
+			var n:int = nh;
+			for ( j=1;j<n;++j) {
+				if( crossFlagArray[j] ) {
+					for ( i=0;(he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
+						pfx = this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)];
+						while( pfx ) {
+							if ( badWord.indexOf(pfx.affixKey)== 0 ) {
+								newWord = pfx.add(guessWordList[j]);
+								if ( newWord) {
+									guessWordList[nh] = newWord;
+									guessOriginalList[nh] = root;
+									crossFlagArray[nh] = pfx.permissionToCombine;
+									nh++;
+								}
+							}
+							pfx = pfx.nextElementWithFlag;
+						}
+					}
+				}
+			}
+			
+			// now handle pure prefixes
+			for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
+				pfx= this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)];
+				while( pfx  ) {
+					if ( badWord.indexOf(pfx.affixKey) == 0 ) {
+						newWord = pfx.add(root);
+						if ( newWord) {
+							guessWordList[nh] = newWord;
+							guessOriginalList[nh] = root;
+							crossFlagArray[nh] = pfx.permissionToCombine;
+							nh++;
+						}
+					}
+					pfx = pfx.nextElementWithFlag; 
+				}
+			}
+				
+		}
+		
+		/*
+		 * ToDo: Since this is a generic algorithm, we might want move this code to StringUtils class.
+		 */
+		private function ngram(n:int, s1:String, s2:String, opt:int):int {
+
+			var i:int,j:int,k:int,m:int,n:int;
+	    	var nscore:int = 0, ns:int, l1:int, l2:int;
+
+			l1 = s1.length;
+			l2 = s2.length;
+			if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase();
+			for ( i = 0; i<l1; i++ ) {
+				if ( s2.indexOf( s1.charAt(i) ) != -1 ) ns++;
+			}
+			nscore = nscore + ns;
+			if ( ns >= 2 ) {
+				for (  j = 2; j<=n; j++ ) {
+					ns = 0;
+					for (  i = 0; i <=(l1-j); i++ ) {
+	//					var tmp:String = s1.substr(i,i+j);
+	//					tmp = s1.substring(i,i+j);
+						if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++;   // it could be signaficantly optimized If we can avoid to use substr() function....
+					}
+					nscore = nscore + ns;
+					if (ns < 2) break;
+				}
+			}
+			ns = 0;
+			if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
+			if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2;
+			ns = (nscore - ((ns > 0) ? ns : 0));
+			return ns;
+			return 1;
+		}
+
+		
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error correction. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		private function ngram1(n:int, s1:String, s2:String, opt:int):int {
+	    	var nscore:int = 0, ns:int, l1:int, l2:int;
+			
+			var i:int,j:int,k:int,m:int,n:int;
+			
+			l1 = s1.length;
+			l2 = s2.length;
+			if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase();
+			for (  j = 1; j<=n; j++ ) {
+				ns = 0;
+				for (  i = 0; i <=(l1-j); i++ ) {
+//					var tmp:String = s1.substr(i,i+j);
+//					tmp = s1.substring(i,i+j);
+					if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++;   // it could be signaficantly optimized If we can avoid to use substr() function....
+				}
+				nscore = nscore + ns;
+				if (ns < 2) break;
+			}
+			ns = 0;
+			if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
+			if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2;
+			ns = (nscore - ((ns > 0) ? ns : 0));
+			return ns;
+			return 1;
+		}
+		
+		/*
+		 * ToDo: since this is a generic algorithm, we might want to move this function to StringUtils class.
+		 */
+		private function leftCommonSubString(s1:String,s2:String, initCap:Boolean, s1CapValue:int):int {
+			var res:int = 1;
+			if ( s1.charCodeAt(0) != s2.charCodeAt(0) && ( !initCap ) && (s1CapValue != s2.charCodeAt(0)) ) return 0;
+			for( var i:int=1; (i< s1.length) && (s1.charCodeAt(i) == s2.charCodeAt(i)); ++i ) {
+				res++;
+			}
+			return res;
+		}
+		
+		
+		public function suggest( result:Array, word:String, capType:int):int {
+			var nsug:int = 0;
+
+			// suggestions for an uppercase word (html -> HTML)
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = capchars(result,word,nsug);
+			}
+			
+			// perhaps we made a typical fault of spelling
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = replchars( result, word, nsug );	
+			}
+			
+			// perhaps we made chose the wrong char from a related set
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = mapchars( result, word, nsug );	
+			}
+
+			// did we swap the order of chars by mistake
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = swapchar( result, word, nsug );	
+			}
+			
+			// did we swap the order of non adjacent chars by mistake
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = longswapchar( result, word, nsug );	
+			}
+
+			// did we just hit the wrong key in place of a good char (case and keyboard)
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = badcharkey( result, word, nsug );	
+			}
+			 // did we add a char that should not be there
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = extrachar( result, word, nsug );	
+			}
+			
+			// did we forgot a char
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = forgotchar( result, word, nsug, capType );	
+			}
+
+			// did we move a char
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = movechar( result, word, nsug );	
+			}
+
+			// did we just hit the wrong key in place of a good char
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = badchar( result, word, nsug, capType );	
+			}
+			
+			// did we double two characters
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = doubletwochars( result, word, nsug );	
+			}
+			
+			// perhaps we forgot to hit space and two words ran together
+			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
+				nsug = twowords( result, word, nsug );	
+			}
+
+			return nsug;
+		}
+		
+		
+		
+		private function mapchars( result:Array, word:String, nsug:int ) :int {
+			if (word.length < 2) return nsug;
+			if ( (nsug == this._maxSug) || (this._attributeMgr.mapFilterTable.length == 0) ) return nsug;
+			var mapTable:Array = this._attributeMgr.mapFilterTable;
+			var counter:int = 0;
+			nsug = map_related(result, word, nsug, 0 ,mapTable, counter);
+			
+			return nsug;
+		}		
+
+		private function map_related( result:Array, word:String, nsug:int, startIndex:int, mapTable:Array, counter:int) :int {
+			var totalCheckCount:int = 8; // for performance issue only... 8 means four level detection...
+			var candidate:String;
+			var in_map:int = 0;
+			var j:int;
+			counter++;
+			if ( counter > totalCheckCount ) return nsug; // for performance issue only...
+			if ( nsug == this._maxSug ) return nsug;
+			if ( startIndex == word.length ) {
+				var cwrd:int = 1;
+				for (  j=0; j < result.length; ++j ) {
+					if ( result[j]== word ) cwrd=0;
+				}
+				if ( cwrd && checkWord(word) ) {
+					result.push(word);
+					nsug++;
+				}
+				return nsug;
+				
+			}
+			for ( var i:int = 0;i<mapTable.length ;++i ) {
+				if ( mapTable[i].mapCharSet.indexOf(word.charAt(startIndex)) != -1 ) {
+					in_map= 1;
+					for ( j =0; j< mapTable[i].mapCharSet.length; ++j ) {
+						candidate = word.substring(0,startIndex) +mapTable[i].mapCharSet.charAt(j)+word.substring(startIndex+1);
+						nsug = map_related(result,candidate,nsug,(startIndex+1),mapTable, counter);
+					}
+				}				
+			}
+			
+			if( !in_map) {
+				nsug = map_related(result,word,nsug,(startIndex+1),mapTable, counter);
+			}
+			return nsug;
+		} 
+		
+		private function twowords( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			var cwrd:int=1;
+			var count:int=0;
+			if (word.length < 3) return result.length;
+			if ( result.length >= this._maxSug ) return result.length;
+			
+			for( var i:int=1;i<word.length;++i) {
+				candidate = word.substring(0,i);
+				if ( !checkWord(candidate) ) continue;
+				candidate = word.substring(i);
+				if ( checkWord(candidate) ) {
+					candidate = word.substring(0,i) +" " + word.substring(i);
+					for ( var j:int=0; j < result.length; ++j ) {
+						if ( result[j]== candidate ) cwrd=0;
+					}
+					if ( cwrd ) {
+						if ( result.length >= this._maxSug ) return result.length;
+						result.push(candidate);
+						nsug++;
+					}
+				}
+			}
+
+			return nsug;
+		}		
+
+		private function doubletwochars( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			var nstate:int=0;
+			if (word.length < 5) return nsug;
+			for (var i:int=2;i<word.length;++i) {
+				if( word.charCodeAt(i) == word.charCodeAt(i-2) ) {
+					nstate++;
+					if ( nstate==3) {
+						candidate = word.substring(0,i-1)+word.substring(i+1);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						nstate = 0;
+					}
+				}else {
+					nstate=0;
+				}
+			}
+			return nsug;
+		}
+
+		private function badchar( result:Array, word:String, nsug:int, capType:int ) :int {
+			if ( this._cAllTry == null ) return nsug;
+			if (word.length < 2) return nsug;
+			var candidate:String;
+			var i:int, j:int;			
+			switch(capType) {
+				case InternalConstants.NOCAP: {
+					// first for init capticalized case...
+					for ( i = 0; i< this._cAllTry.length;++i) {
+						candidate = this._cAllTry.charAt(i)+word.substring(1);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					// for the rest of the word...
+					for ( i = 0; i< this._cLowerTry.length;++i) {
+						for ( j=1;j<word.length;++j) {
+							candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+					}
+					break;
+				}
+				case InternalConstants.INITCAP:{
+					// first for init capticalized case...
+					for ( i = 0; i< this._cAllTry.length;++i) {
+						candidate = this._cAllTry.charAt(i)+word.substring(1);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					// for the rest of the word...
+					for ( i = 0; i< this._cLowerTry.length;++i) {
+						for ( j=1;j<word.length;++j) {
+							candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+					}
+					break;
+				}
+				case InternalConstants.HUHCAP: { 
+				}
+				case InternalConstants.HUHINITCAP:{ 
+					for ( i = 0; i< this._cAllTry.length;++i) {
+						for ( j=0;j<word.length;++j) {
+							candidate = word.substring(0,j)+this._cAllTry.charAt(i)+word.substring(j+1);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+					}
+					break;
+				}
+				case InternalConstants.ALLCAP: {
+					for ( i = 0; i< this._cUpperTry.length;++i) {
+						for ( j=0;j<word.length;++j) {
+							candidate = word.substring(0,j)+this._cUpperTry.charAt(i)+word.substring(j+1);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+					}
+					break;
+				}
+			}
+			
+			return nsug;
+		}		
+
+		// did we move a char
+		private function movechar( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			var i:int,j:int;
+			var char:String;
+			if (word.length < 3) return nsug;
+			for ( i=0;i<word.length-2;++i) {
+				char = word.charAt(i);
+				for ( j=i+2;j<word.length;++j) {
+					candidate = word.substring(0,i)+word.substring(i+1,j+1)+char+word.substring(j+1);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+			}
+			
+			for ( i=word.length-1;i>=2;--i) {
+				char = word.charAt(i);
+				for ( j=i-2;j>=0; --j) {
+					candidate = word.substring(0,j)+char+word.substring(j,i)+word.substring(i+1);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+			}
+			
+			return nsug;
+		}		
+
+		private function forgotchar( result:Array, word:String, nsug:int, capType:int ) :int {
+			if ( this._cAllTry == null ) return nsug;
+			var candidate:String;
+			var i:int, j:int;			
+			if (word.length < 2) return nsug;
+			switch(capType) {
+				case InternalConstants.NOCAP: {
+					for (i =0; i< this._cAllTry.length; ++i ) {
+						candidate= _cAllTry.charAt(i) + word.substring(0);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+
+					for (i =0; i< this._cLowerTry.length; ++i ) {
+						for ( j=1; j< word.length;j++) {
+							candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+						candidate= word+_cLowerTry.charAt(i);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					break;
+				}
+				case InternalConstants.INITCAP:{
+					// first for init capticalized case...
+					for (i =0; i< this._cAllTry.length; ++i ) {
+						candidate= _cAllTry.charAt(i) + word.substring(0);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+
+					for (i =0; i< this._cLowerTry.length; ++i ) {
+						for ( j=1; j< word.length;j++) {
+							candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+						candidate= word+_cLowerTry.charAt(i);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					break;
+				}
+				case InternalConstants.HUHCAP: { 
+				}
+				case InternalConstants.HUHINITCAP:{ 
+					for (i =0; i< this._cAllTry.length; ++i ) {
+						for ( j=1; j< word.length;j++) {
+							candidate= word.substring(0,j)+_cAllTry.charAt(i) + word.substring(j);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+						candidate= word+_cAllTry.charAt(i);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					break;
+				}
+				case InternalConstants.ALLCAP: {
+					for (i =0; i< this._cUpperTry.length; ++i ) {
+						for ( j=0; j< word.length;j++) {
+							candidate= word.substring(0,j)+_cUpperTry.charAt(i) + word.substring(j);
+							nsug = testSuggestion( result,candidate, nsug);
+							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+						}
+						candidate= word+_cUpperTry.charAt(i);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					break;
+				}
+			}
+			return nsug;
+		}		
+
+		// error is word has an extra letter it does not need 
+		private function extrachar( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			if (word.length < 2) return nsug;
+			for ( var i:int=0; i< word.length ; ++i ) {
+				candidate = word.substring(0,i) + word.substring(i+1);
+				nsug = testSuggestion( result,candidate, nsug);
+				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+			}
+			return nsug;
+		}		
+		
+		// error is wrong char in place of correct one (case and keyboard related version)
+		private function badcharkey( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			if (word.length < 2) return nsug;
+			var startIndex:int = 0;
+			// swap out each char one by one and try uppercase and neighbor
+			// keyboard chars in its place to see if that makes a good word
+			for ( var i:int =0; i<word.length; ++i) {
+				// check with uppercase letters
+				if ( word.charAt(i).toLocaleUpperCase() != word.charAt(i) ) {
+					candidate = word.substring(0,i)+word.charAt(i).toLocaleUpperCase()+word.substring(i+1);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+				// check neighbor characters in keyboard string
+				if ( this._ckey == null ) continue;
+				startIndex = this._ckey.indexOf(word.charAt(i),startIndex);
+				while ( startIndex != -1 ) {
+					if ( (startIndex!=0) && (_ckey.charAt(startIndex-1) != "|" ) ) {
+						candidate = word.substring(0,i)+_ckey.charAt(startIndex-1)+word.substring(i+1);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					if ( (_ckey.charAt(startIndex+1)!="|") && (startIndex != _ckey.length - 1) ) {
+						candidate = word.substring(0,i)+_ckey.charAt(startIndex+1) + word.substring(i+1);
+						nsug = testSuggestion( result,candidate, nsug);
+						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+					}
+					startIndex = this._ckey.indexOf(word.charAt(i),startIndex+1);
+				}
+			}
+			
+			return nsug;
+		}		
+
+		private function longswapchar( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			if (word.length < 2) return nsug;
+			for ( var i:int =0 ; i< word.length-2; ++i ) {
+				for ( var j:int = i+2;j< word.length;++j) {
+					candidate = word.substring(0,i)+ word.charAt(j) + word.substring(i+1,j) + word.charAt(i) + word.substring(j+1);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+			}
+			return nsug;
+		}		
+
+		private function swapchar( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			if (word.length < 2) return nsug;
+			var i:int;
+			var wl:int = word.length;
+			// try swapping adjacent chars one by one
+			for (i=0;i< wl-1;++i) {
+				candidate = word.substring(0,i)+word.charAt(i+1)+word.charAt(i) + word.substring(i+2);
+				nsug = testSuggestion( result,candidate, nsug);
+				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+			}
+			
+			if ( wl == 4 || wl == 5 ) {
+				candidate = word.charAt(1) + word.charAt(0);
+				if ( wl == 5) candidate +=word.charAt(2);
+				candidate += word.charAt(wl - 1) + word.charAt(wl - 2); 
+				nsug = testSuggestion( result,candidate, nsug);
+				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				if ( wl == 5 )  {
+					candidate = word.charAt(0) + word.charAt(2) + word.charAt(1) + candidate.substr(3);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+			}
+			return nsug;
+			
+		}		
+		private function replchars( result:Array, word:String, nsug:int ) :int {
+			var candidate:String;
+			if (word.length < 2) return nsug;
+			var searchIndex:int=0;
+			if ( (this._attributeMgr.simpleFilterTable==null) || (this._attributeMgr.simpleFilterTable.length == 0) ) return nsug;
+			for ( var i:int = 0; i < this._attributeMgr.simpleFilterTable.length; ++i ) {
+				while ( (searchIndex = word.indexOf( this._attributeMgr.simpleFilterTable[i].matchString,searchIndex)) != -1 ){
+					searchIndex = searchIndex + this._attributeMgr.simpleFilterTable[i].matchString.length;
+					candidate = word.substr(0, searchIndex-this._attributeMgr.simpleFilterTable[i].matchString.length) + 
+					this._attributeMgr.simpleFilterTable[i].replacement + 
+					word.substr(searchIndex);
+					nsug = testSuggestion( result,candidate, nsug);
+					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
+				}
+				
+			}
+			return nsug;
+		}
+		
+		private function capchars( result:Array, word:String, nsug:int) : int {
+			var candidate:String = word.toLocaleUpperCase();
+			return testSuggestion(result,candidate,nsug);
+		}
+		
+		private function testSuggestion(result:Array, word:String, nsug:int):int {
+			var cwrd:int=1;
+			if ( result.length >= this._maxSug ) return nsug;
+			for ( var i:int=0; i < result.length; ++i ) {
+				if ( result[i]== word ) cwrd=0;
+			}
+			
+			if ( (cwrd) && checkWord(word) ) {
+				result.push(word);
+				nsug++;
+			}
+			return nsug;
+		}
+
+		// see if a candidate suggestion is spelled correctly
+		// needs to check both root words and words with affixes
+		
+		// ToDo the following in next release...
+		// obsolote MySpell-HU modifications:
+		// return value 2 and 3 marks compounding with hyphen (-)
+		// `3' marks roots without suffix   
+
+		private function checkWord(word:String):int {
+			var rv:HashEntry = null;
+			var nosuffix:int =0;
+			if ( this._attributeMgr ) {
+				rv = _attributeMgr.lookup(word);
+				if ( rv ) {
+					if ( (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(this._attributeMgr.noSuggest) )  ){
+						return 0;
+					}
+					while ( rv ) {
+						if ( (rv.affixFlagVector) &&  ( rv.testAffix(this._attributeMgr.needAffix) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) || rv.testAffix(this._attributeMgr.onlyInCompound) )  ) {
+							rv = rv.next
+						}else break;
+					}
+				}else rv = _attributeMgr.optPrefixCheck2(word, 0,0) // only prefix, and prefix + suffix XXX
+				
+				if ( rv ) {
+					nosuffix = 1;
+				}else {
+					rv = _attributeMgr.optSuffixCheck2(word,0,null,0,0);
+				}
+				//this is added after we have two level suffix stripping
+				if (!rv &&  this._attributeMgr.haveContClass) {
+					rv = this._attributeMgr.optTwoSuffixCheck(word, 0, null, 0);
+					if (!rv) rv = this._attributeMgr.optTwoPrefixCheck(word,1, 0);
+				}
+				
+				// check forbidden words
+				if ( (rv) && (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) 
+				|| rv.testAffix(this._attributeMgr.noSuggest) || rv.testAffix(this._attributeMgr.onlyInCompound) ) ) {
+					return 0;
+				}
+				if ( rv ) {
+					//// XXX obsolote ToDo
+					return 1;
+				}
+				
+			}
+			return 0;
+		}
+		
+	}
+}
+
+
+internal class GuessWord {
+	private var _score:int;
+	private var _key:String;
+	private var _original:String;
+	
+	public function GuessWord(score:int, key:String, original:String){
+		this.key = key;
+		this.score = score;
+		this.original = original;
+	}
+	
+	public function get score():int {
+		return this._score;
+	}
+	public function set score(value:int) :void {
+		this._score = value;
+	}
+	
+	public function get key():String {
+		return this._key;
+	}
+	public function set key(value:String) :void {
+		this._key = value;
+	}
+	public function get original():String {
+		return this._original;
+	}
+	public function set original(value:String) :void {
+		this._original = value;
+	}
+}
+
+internal class SuggestionEntry {
+	import com.adobe.linguistics.spelling.core.HashEntry;
+	private var _score:int;
+	private var _key:String;
+	private var _hashEntry:HashEntry; 
+	
+	public function SuggestionEntry(score:int, key:String, hashEntry:HashEntry) {
+		this.key = key;
+		this.score = score;
+		this.hashEntry = hashEntry;
+		
+	}
+	
+	public function get score():int {
+		return this._score;
+	}
+	public function set score(value:int) :void {
+		this._score = value;
+	}
+	
+	public function get key():String {
+		return this._key;
+	}
+	public function set key(value:String) :void {
+		this._key = value;
+	}
+	
+	public function get hashEntry():HashEntry {
+		return this._hashEntry;
+	}
+	
+	public function set hashEntry(value:HashEntry ) :void {
+		this._hashEntry = value;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
new file mode 100644
index 0000000..93ba707
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	import com.adobe.linguistics.spelling.UserDictionaryInternal;
+	
+	public class UserDictionaryEngine
+	{
+		// Private properties
+		private var _dictionaryList:Array;		// get only
+		private var _userDict:UserDictionaryInternal;
+
+		public function UserDictionaryEngine(ud:UserDictionaryInternal=null)
+		{
+			_dictionaryList = new Array();
+		}
+		public function addDictionary(userDictionary:UserDictionaryInternal):Boolean
+		{
+			if ( (userDictionary == null) ) return false;
+			
+			for ( var i:int = 0;i < _dictionaryList.length; ++i ) {
+				if ( userDictionary == _dictionaryList[i] )
+					return false;
+			} 
+			_dictionaryList.push(userDictionary);
+			return true;
+		}
+
+		public function removeDictionary(userDictionary:UserDictionaryInternal):Boolean
+		{
+			
+			for ( var i:int =0; i < _dictionaryList.length; ++i ) {
+				if ( userDictionary == _dictionaryList[i] ) {
+					_dictionaryList.splice(i,1);
+					return true;
+				}
+			}
+			return false;
+		}
+		
+		public function spell( word:String ) :Boolean {
+			var result:Boolean = false;
+			for ( var i:int =0; (i < _dictionaryList.length) && (!result);++i ) {
+				_userDict = _dictionaryList[i];
+				if ( _userDict ) {
+					result = (_userDict._wordList.lookup(word) != -1);
+				}
+			}
+			return result;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as
new file mode 100644
index 0000000..5954c21
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	/**
+	 * public interface Collection The root interface in the collection 
+	 * hierarchy. A collection represents a group of objects, known as 
+	 * its elements. Some collections allow duplicate elements and others 
+	 * do not. Some are ordered and others unordered. The SDK does not 
+	 * provide any direct implementations of this interface: it provides 
+	 * implementations of more specific subinterfaces like Set and List. 
+	 */
+	 
+	 /**
+	  * ToDo: add hashCode() function
+	  * 	add remove()/add() function
+	  */
+	 
+	public interface Collection
+	{
+
+		/**
+		 * The number of elements in this collection.
+		 * @Returns the number of elements in this collection.
+		 */
+		function get size():int;
+		
+		/**
+		 * Tests if the collection is empty.
+		 * 
+		 * @ Returns true if this collection contains no elements.
+		 */
+		function isEmpty():Boolean
+		
+		/**
+		 * Determines if the collection contains the specified element.
+		 * 
+		 * @ obj: element whose presence in this collection is to be tested.
+		 * 
+		 * @ Returns true if this collection contains the specified element.
+		 */
+		function contains( obj:* ) : Boolean
+		
+		/**
+		 * Removes all of the elements from this collection (optional operation).
+		 */
+		function clear():void
+		
+		/**
+		 * Returns an iterator over the elements in this collection. There are 
+		 * no guarantees concerning the order in which the elements are returned 
+		 * (unless this collection is an instance of some class that provides a guarantee). 
+		 *
+		 * @an Iterator over the elements in this collection
+		 */
+		function getIterator():Iterator
+		
+		/**
+		 * Returns an array containing all of the elements in this collection. 
+		 * If the collection makes any guarantees as to what order its elements 
+		 * are returned by its iterator, this method must return the elements 
+		 * in the same order.
+		 * 
+		 * @return An array.
+		 */
+		function toArray():Array
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as
new file mode 100644
index 0000000..16611ad
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as
@@ -0,0 +1,28 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	public interface Enumeration
+	{
+		function hasMoreElements():Boolean;
+		function nextElement():*;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as
new file mode 100644
index 0000000..cf38c81
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as
@@ -0,0 +1,179 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+package com.adobe.linguistics.spelling.core.container
+{
+	import flash.utils.Dictionary;
+	
+	/**
+	 * A hash table
+	 */
+	public class HashTable implements Collection
+	{
+		protected var _map:Dictionary;
+		protected var _elementNum:int;
+		
+		/**
+		 * Initializes a new hash table.
+		 * 
+		 * @param size The size of the hash table.
+		 * @param hash A hashing function.
+		 */
+		public function HashTable(useWeakReferences:Boolean = true)
+		{
+			_map = new Dictionary( useWeakReferences );
+			_elementNum = 0;
+		}
+
+		public function put(key:*, value:*) : void
+		{
+			_map[key] = value;
+			++_elementNum;
+		}
+
+		public function remove(key:*) : void
+		{
+			delete _map[key];
+			--_elementNum;
+		}
+
+		public function containsKey(key:*) : Boolean
+		{
+			return _map.hasOwnProperty( key );
+		}
+		
+		public function containsValue(value:*) : Boolean
+		{
+			for ( var key:* in _map )
+			{
+				if ( _map[key] == value )
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public function contains(value:*):Boolean {
+			return containsValue(value);
+		}
+
+		public function getElement(key:* ):* {
+			return _map[key];
+		}
+				
+		/**
+		 * @inheritDoc
+		 */
+		public function clear() : void
+		{
+			for ( var key:* in _map )
+			{
+				remove( key );
+			}
+		}
+		
+		/**
+		 * @inheritDoc
+		 */
+		public function getIterator():Iterator
+		{
+			return null;
+		}
+		
+		/**
+		 * @inheritDoc
+		 */
+		public function get size():int
+		{
+			return _elementNum;
+		}
+		
+		/**
+		 * @inheritDoc
+		 */
+		public function isEmpty():Boolean
+		{
+			return _elementNum == 0;
+		}
+
+		public function get keys() : Array
+		{
+			var _keys:Array = [];
+
+			for (var key:* in _map)
+			{
+				_keys.push( key );
+			}
+			return _keys;
+		}
+		
+		public function get elements() : Array
+		{
+			var _values:Array = [];
+
+ 			for each ( var value:* in _map ) {
+				_values.push( value );
+			}
+			return _values;
+		}
+
+		/**
+		 * @inheritDoc
+		 */
+		public function toArray():Array
+		{
+			return keys;
+		}
+		
+		/**
+		 * Prints out a string representing the current object.
+		 * 
+		 * @return A string representing the current object.
+		 */
+		public function toString():String
+		{
+			return "[HashTable, size=" + size + "]";
+		}
+		
+		public function get hashMap():Dictionary {
+			return this._map;
+		}
+		
+		/**
+		 * Need refine... Possible solution is that we can use two function paramter to control the input and output. 
+		 * 
+		 *
+		 */
+		public function watchEntries(func:Function=null):Array {
+			if ( func == null )
+				return null;
+			var res:Array = new Array();
+			for (var curKey:* in _map)
+			{
+				if ( func( curKey, _map[curKey] ) ) {
+					res.push( curKey );
+				}
+			}
+			return (res.length == 0)? null: res;
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as
new file mode 100644
index 0000000..555d6a3
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as
@@ -0,0 +1,263 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	/**
+	 * BinaryHeap implementation of priority queue. The heap is either a 
+	 * minimum or maximum heap as determined by parameters passed to constructor. 
+	 * 
+	 */
+	public final class Heap implements Collection
+	{
+		private var __size:int;
+		private var __count:int;
+		private var __compare:Function;
+		public var __heap:Array;
+		
+		/**
+		 * Create a new heap.
+		 * 
+		 * @param size The heap's maximum capacity.
+		 * @param compare A comparison function for sorting the heap's data.
+		 *        If no function is passed, the heap uses default function.
+		 */
+		public function Heap(size:int=1000, compare:Function = null)
+		{
+			__count = 0;
+			__heap = new Array(__size = size + 1);
+			
+			if (compare == null)
+				__compare = function(a:int, b:int):int { return a - b; };
+			else
+				__compare = compare;
+		}
+
+		/**
+		 * The maximum capacity.
+		 */
+		public function get maxSize():int
+		{
+			return __size;
+		}
+
+		public function isEmpty():Boolean
+		{
+			return false;
+		}
+		
+		public function toArray():Array
+		{
+			return __heap.slice(1, __count + 1);
+		}
+		
+		public function toString():String
+		{
+			return "[Heap, size=" + __size +"]";
+		}
+		
+		public function dump():String
+		{
+			var k:int = __count + 1;
+			var s:String = "Heap\n{\n";
+			for (var i:int = 1; i < k; i++)
+				s += "\t" + __heap[i] + "\n";
+			s += "\n}";
+			return s;
+		}
+		
+		/**
+		 * The front item.
+		 */
+		public function get front():*
+		{
+			return __heap[1];
+		}
+		
+		/**
+		 * Enqueues.
+		 * @param obj The data to enqueue.
+		 * @return False if the queue is full, otherwise true.
+		 */
+		public function enqueue(obj:*):Boolean
+		{
+			if (__count + 1 < __size){
+				__heap[++__count] = obj;
+				
+				var i:int = __count;
+				var tmp:* = __heap[i];
+				var v:*;
+				var parent:int = i >> 1;
+				
+				if (__compare != null)
+				{
+					while (parent > 0){
+						 v = __heap[parent];
+						if (__compare(tmp, v) < 0){
+							__heap[i] = v;
+							i = parent;
+							parent >>= 1;
+						}
+						else break;
+					}
+				}else{
+					while (parent > 0){
+						v = __heap[parent];
+						if (tmp - v < 0){
+							__heap[i] = v;
+							i = parent;
+							parent >>= 1;
+						}
+						else break;
+					}
+				}
+				__heap[i] = tmp;
+				return true;
+			}
+			return false;
+		}
+		
+		/**
+		 * Dequeues.
+		 * @return The heap's front item or null if it is empty.
+		 */
+		public function dequeue():*
+		{
+			if (__count >= 1){
+				var o:* = __heap[1];
+				
+				__heap[1] = __heap[__count];
+				delete __heap[__count];
+				
+				var tmp:* = __heap[i];
+				var i:int = 1;
+				var v:*;
+				var child:int = i << 1;
+				
+				if (__compare != null) {
+					while (child < __count) {
+						if (child < __count - 1) {
+							if (__compare(__heap[child], __heap[int(child + 1)]) > 0)
+								child++;
+						}
+						v = __heap[child];
+						if (__compare(tmp, v) > 0){
+							__heap[i] = v;
+							i = child;
+							child <<= 1;
+						}
+						else break;
+					}
+				}else{
+					while (child < __count){
+						if (child < __count - 1){
+							if (__heap[child] - __heap[int(child + 1)] > 0)
+								child++;
+						}
+						v = __heap[child];
+						if (tmp - v > 0){
+							__heap[i] = v;
+							i = child;
+							child <<= 1;
+						}
+						else break;
+					}
+				}
+				__count--;
+				__heap[i] = tmp;
+				return o;
+			}
+			return null;
+		}
+		
+		/**
+		 * Tests if a given item exists.
+		 */
+		public function contains(obj:*):Boolean
+		{
+			for (var i:int = 1; i <= __count; i++){
+				if (__heap[i] === obj)
+					return true;
+			}
+			return false;
+		}
+		
+		public function clear():void
+		{
+			__heap = new Array(__size);
+			__count = 0;
+		}
+		
+		public function getIterator():Iterator
+		{
+			return new HeapIterator(this);
+		}
+
+		public function get size():int
+		{
+			return __count;
+		}
+		
+	}
+}
+
+import com.adobe.linguistics.spelling.core.container.Heap;
+import com.adobe.linguistics.spelling.core.container.Iterator;
+
+internal class HeapIterator implements Iterator
+{
+	private var __values:Array;
+	private var __length:int;
+	private var __cursor:int;
+	
+	public function HeapIterator(heap:Heap)
+	{
+		__values = heap.toArray();
+		__cursor = 0;
+		__length = __values.length;
+	}
+	
+	public function get data():*
+	{
+		return __values[__cursor];
+	}
+	
+	public function set data(obj:*):void
+	{
+		__values[__cursor] = obj;
+	}
+	
+	public function start():void
+	{
+		__cursor = 0;
+	}
+	
+	public function hasNext():Boolean
+	{
+		return __cursor < __length;
+	}
+	
+	public function next():*
+	{
+		return __values[__cursor++];
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as
new file mode 100644
index 0000000..4abe889
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as
@@ -0,0 +1,64 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	/**
+	 * public interface Iterator
+	 * An iterator over a collection. Iterator takes the place of Enumeration 
+	 * in the AS collections framework. Iterators differ from enumerations in 
+	 * two ways:
+	 * Iterators allow the caller to remove elements from the underlying 
+	 * collection during the iteration with well-defined semantics.
+	 * Method names have been improved. 
+	 */
+	public interface Iterator
+	{
+
+		/**
+		 * Grants access to the current item being referenced by the iterator.
+		 * This provides a quick way to read or write the current data.
+		 * Dirty interface, will remove in next version.
+		 */
+		function get data():*
+		function set data(obj:*):void	
+
+		/**
+		 * Seek the iterator to the first item in the collection.
+		 */
+		function start():void
+
+		/**
+		 * Returns the next element in the iteration.
+		 * 
+		 */
+		function next():*
+		
+		/**
+		 * Returns true if the iteration has more elements.
+		 * 
+		 * @Returns true if the iteration has more elements.
+		 */
+		function hasNext():Boolean
+		
+		}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as
new file mode 100644
index 0000000..32525e7
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as
@@ -0,0 +1,195 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	import flash.utils.Dictionary;
+	
+	/**
+	 * A collection that contains no duplicate elements. More formally, sets 
+	 * contain no pair of elements e1 and e2 such that e1.equals(e2), and at 
+	 * most one null element. As implied by its name, this interface models 
+	 * the mathematical set abstraction.
+	 */
+	public final class Set implements Collection
+	{
+		private var __size:int;
+		private var __set:Dictionary = new Dictionary(true);
+		
+		/**
+		 * Creates a empty set.
+		 */
+		public function Set()
+		{
+			__set = new Dictionary();			
+		}
+		
+
+		public function contains(obj:*):Boolean
+		{
+			return __set[obj] != undefined;
+		}
+		
+		public function clear():void
+		{
+			__set = new Dictionary();
+			__size = 0;
+		}
+		
+		public function get data():Dictionary {
+			return this.__set;
+		}
+		
+		public function getIterator():Iterator
+		{
+			return new SetIterator(this);
+		}
+		
+		public function get size():int
+		{
+			return __size;
+		}
+		
+		public function isEmpty():Boolean
+		{
+			return __size == 0;
+		}
+
+		/**
+		 * Reads an item from the set.
+		 * 
+		 * @param obj The item to retrieve.
+		 * @return The item matching the obj parameter or null.
+		 */
+		public function lookup(obj:*):*
+		{
+			var val:* = __set[obj];
+			return val != undefined ? val : null;
+		}
+
+		/**
+		 * Adds the specified element to this set if it is not already present (optional operation).
+		 * 
+		 * @param obj The item to be added.
+		 */
+		public function insert(obj:*):void
+		{
+			if (obj == null) return;
+			if (obj == undefined) return;
+			if (__set[obj]) return;
+			
+			__set[obj] = obj;
+			__size++;
+		}
+		
+		/**
+		 * Removes the specified element from this set if it is present (optional operation).
+		 * 
+		 * @param  obj The item to be removed
+		 * @return The removed item or null.
+		 */
+		public function remove(obj:*):Boolean
+		{
+			if (__set[obj] != undefined)
+			{
+				delete __set[obj];
+				__size--;
+				return true;
+			}
+			return false;
+		}
+		
+		public function toArray():Array
+		{
+			var a:Array = new Array(__size);
+			var j:int;
+			for (var i:* in __set) a[j++] = i;
+			return a;
+		}
+		
+		/**
+		 * Return a string representing the current object.
+		 */
+		public function toString():String
+		{
+			return "[Set, size=" + size + "]";
+		}
+		
+		/**
+		 * Prints out all elements (debug use only).
+		 */
+		public function dump():String
+		{
+			var s:String = "Set:\n";
+			for each (var i:* in __set)
+				s += "[val: " + i + "]\n";
+			return s;
+		}
+	}
+
+}
+
+
+import com.adobe.linguistics.spelling.core.container.Iterator
+import com.adobe.linguistics.spelling.core.container.Set;
+
+internal class SetIterator implements Iterator
+{
+	private var __cursor:int;
+	private var __size:int;
+	private var __s:Set;
+	private var __a:Array;
+
+	public function start():void
+	{
+		__cursor = 0;
+	}
+
+	public function get data():*
+	{
+		return __a[__cursor];
+	}
+	
+	public function set data(obj:*):void
+	{
+		__s.remove(__a[__cursor]);
+		__s.insert(obj);
+	}	
+	
+	public function SetIterator(s:Set)
+	{
+		__cursor = 0;
+		__size = s.size;
+		__s = s;
+		__a = s.toArray();
+	}
+	
+	public function next():*
+	{
+		return __a[__cursor++];
+	}
+	
+	public function hasNext():Boolean
+	{
+		return __cursor < __size;
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as
new file mode 100644
index 0000000..3a0e8d1
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as
@@ -0,0 +1,283 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.container
+{
+	import com.adobe.linguistics.spelling.core.utils.*;
+	public final class SparseHashTable implements Collection
+	{
+		
+		private var _keyTable:Array;
+		private var _elementTable:Array;
+		private var _hashSize:int;
+		private var _tableCapacity:int;
+		private var _loadFactor:Number;
+		private var _elementNum:int;
+		private var _deletedObject:Object = new Object();
+		
+		/**
+		 * A simple function for hashing strings.
+		 */
+		private function hashString(s:String):int
+		{
+			var hash:int = 0, i:int, k:int = s.length, ROTATE_LEN:int = 5;
+			for ( i =0; i < 4 && !isNaN(s.charCodeAt(i)); ++i ) {
+				hash = ( hash << 8 ) | ( s.charCodeAt(i) )
+			}
+			while ( !isNaN(s.charCodeAt(i)) ) {
+				(hash) = ((hash) << (ROTATE_LEN)) | (((hash) >> (32 - ROTATE_LEN)) & ((1 << (ROTATE_LEN))-1));
+				hash ^= ( s.charCodeAt(i) );
+				++i; 
+			}
+			return (hash > 0) ? hash : -hash; // or use uint conversion to convert minus number to plus number.... still debate//
+		}
+//		private function hashString(s:String):int
+//		{
+//			var hash:int = 0, i:int, k:int = s.length;
+//			for (i = 0; i < k; i++) hash += (i + 1) * s.charCodeAt(i);
+//			return hash;
+//		}
+		
+		/**
+		 * A simple function for hashing integers.
+		 */
+		private function hashNumber(n:Number):int
+		{
+			var i:int = int(n);
+			return int(i>0? i:-i);
+		}
+		
+		private function hash(key:*):int {
+			if (key is Number ) {
+				return hashNumber(key);
+			}else if (key is String ) {
+				return hashString(key);
+			}
+			
+			if (key.hasOwnProperty("hashCode"))
+            	return key.hashCode()>0 ? key.hashCode() : -key.hashCode();
+        	else
+            	return int(key)>0 ? int(key) : -int(key);
+		}
+
+		public function SparseHashTable(initialCapacity:int = 128, loadFactor:Number = 0.75)
+		{
+			initHash(initialCapacity, loadFactor);
+		}
+		
+		private function initHash(initialCapacity:int = 128, loadFactor:Number = 0.75):void {
+			if ( !(initialCapacity > 0) ||  !( loadFactor > 0 && loadFactor < 1) )
+				return; //input is invalid, should through exception or ...
+			_loadFactor = loadFactor;
+			_hashSize = initialCapacity;
+			_tableCapacity = MathUtils.nextPrime( int(_hashSize/loadFactor) );
+			_keyTable = new Array(_tableCapacity);
+			_elementTable = new Array(_tableCapacity);
+			_elementNum = 0;
+			clear();
+		}
+		
+		private function getKeyPosition(key:*):int {
+			var hashValue:int = hash(key);
+			var pos:int;
+			if ( hashValue < 0 ) {
+				trace ( "hashValue shouldn't be negative integer" );
+				return -1;
+			}
+			//Quadratic Probing
+			for ( var i:int =0; i < _tableCapacity; ++i ) {
+				pos = (hashValue+i*i)%_tableCapacity ; //hi=(h(key)+i*i)%m 0≤i≤m-1 
+				if ( _keyTable[pos] == null ) 
+					break;
+				if ( _keyTable[pos] == key ) {
+					return pos;
+				}
+			}
+			return -1;						
+		}
+
+		private function calculateKeyPostion(key:*):int {
+			var hashValue:int = hash(key);
+			var pos:int;
+			if ( hashValue < 0 ) {
+				trace ( "Position shouldn't be negative" );
+				return -1;
+			}
+			//Quadratic Probing
+			for ( var i:int =0; i < _tableCapacity; ++i ) {
+				pos = (hashValue+i*i)%_tableCapacity ; //hi=(h(key)+i*i)%m 0≤i≤m-1 
+				if ( (_keyTable[pos] == null ) || 
+				( _keyTable[pos] == _deletedObject ) ) {
+					// insert successfully
+					return pos;
+				}
+			}
+			return -1; // hash table is full now. it should never happen.
+			
+		}		
+		
+
+		protected function rehash():void {
+			if ( _hashSize == _elementNum ) {
+				var oldKeyTable:Array = _keyTable;
+				var oldElementTable:Array = _elementTable;
+				initHash(_hashSize*2, _loadFactor);
+				for ( var i:int =0 ; i < oldKeyTable.length; ++i ) {
+					if (oldKeyTable[i]==null 
+					|| oldKeyTable[i] == _deletedObject) {
+						continue;
+					}
+					put(oldKeyTable[i],oldElementTable[i] );
+				}
+				oldKeyTable=null;
+				oldElementTable=null;
+			}
+		}
+		
+		public function put( key:*, value:* ) :Boolean {
+			if ( _hashSize == _elementNum ) {
+				rehash();
+			}
+
+			if ( containsKey(key)  ) {
+				trace ( "Contains the same Key in the table" );
+				return false;
+			}
+			
+			var pos:int = calculateKeyPostion(key);
+			if ( pos < 0 ) {
+				trace ( "SparseHash internal error." );
+				return false;
+			}
+
+			++_elementNum;
+			_keyTable[pos] = key;
+			_elementTable[pos] = value;
+			return true;
+		}
+
+		public function remove(key:*):* {
+			var pos:int = getKeyPosition(key);
+			var res:* = (pos < 0) ? null:_elementTable[pos];
+			if ( pos >= 0 ) {
+				--_elementNum;
+				_keyTable[pos] =_deletedObject;
+				_elementTable[pos] = _deletedObject;
+			}
+			return res;
+		}
+		
+		public function contains(value:*):Boolean {
+			return containsValue(value);
+		}
+		
+		/**
+		 * Determines if the collection contains the specified element.
+		 * 
+		 * @ obj: element whose presence in this collection is to be tested.
+		 * 
+		 * @ Returns true if this collection contains the specified element.
+		 */
+		public function containsKey(key:*):Boolean {
+			var pos:int = getKeyPosition(key);
+			return (pos >= 0);	
+		}
+		
+		public function containsValue(value:*):Boolean {
+			for ( var i:int =0; i < _tableCapacity; ++i ) {
+				if ( (_keyTable[i] == null ) || 
+				( _keyTable[i] == _deletedObject ) ) {
+					continue;
+				}
+				if ( _elementTable[i].value == value ) 
+					return true;
+			}
+			return false;
+		}
+		
+		public function getElement(key:* ):* {
+			var pos:int = getKeyPosition(key);
+			return (pos < 0) ? null:_elementTable[pos];
+			
+		}
+
+		/**
+		 * The number of elements in this collection.
+		 * @Returns the number of elements in this collection.
+		 */
+		public function get size():int {
+			return _elementNum;
+		}
+		
+		public function get elements():Enumeration {
+			return null;
+		}
+		
+		public function get keys():Enumeration {
+			return null;
+		}
+		
+		/**
+		 * Tests if the collection is empty.
+		 * 
+		 * @ Returns true if this collection contains no elements.
+		 */
+		public function isEmpty():Boolean {
+			return (_elementNum==0);
+		}
+		
+		
+		/**
+		 * Removes all of the elements from this collection (optional operation).
+		 */
+		public function clear():void {
+			var i:int;
+			for( i=0;i< _tableCapacity;++i) {
+				_keyTable[i] = null;
+				_elementTable[i] = null;
+			}
+		}
+		
+		/**
+		 * Returns an iterator over the elements in this collection. There are 
+		 * no guarantees concerning the order in which the elements are returned 
+		 * (unless this collection is an instance of some class that provides a guarantee). 
+		 *
+		 * @an Iterator over the elements in this collection
+		 */
+		public function getIterator():Iterator {
+			return null;
+		}
+		
+		/**
+		 * Returns an array containing all of the elements in this collection. 
+		 * If the collection makes any guarantees as to what order its elements 
+		 * are returned by its iterator, this method must return the elements 
+		 * in the same order.
+		 * 
+		 * @return An array.
+		 */
+		public function toArray():Array {
+			return _keyTable;
+		}		
+		
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as
new file mode 100644
index 0000000..e38052e
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as
@@ -0,0 +1,47 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.env
+{
+	/*
+	 * External-Internal public Constant properties...
+	 * In the future, we might want to merge this class with InternalConstant class...
+	 */
+	
+	public class ExternalConstants
+	{
+
+		// casing
+		static public const NOCAP:int =					0;
+		static public const INITCAP:int =				1;
+		
+		
+		static public const SPELL_COMPOUND:int=			(1 << 0);
+		static public const SPELL_FORBIDDEN:int=		(1 << 1);
+		static public const SPELL_ALLCAP:int=			(1 << 2);
+		static public const SPELL_NOCAP:int=			(1 << 3);
+		static public const SPELL_INITCAP:int=			(1 << 4);
+
+		public function ExternalConstants()
+		{
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as
new file mode 100644
index 0000000..e14fc31
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.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.core.env
+{
+	/*
+	 * Internal-Internal public Constant properties...
+	 * In the future, we might want to merge this class with ExternalConstant class...
+	 * This one is sharing by HunSpell related algorithm...
+	 */
+	public class InternalConstants
+	{
+		// casing
+		static public const NOCAP:int =					1;
+		static public const INITCAP:int =				2;
+		static public const ALLCAP:int =				4;
+		static public const HUHCAP:int =				8;
+		static public const HUHINITCAP:int =			16;
+
+		
+		static public const FLAG_LONG:int = 			1;
+		static public const FLAG_NUM:int = 				2;
+		static public const FLAG_UNI:int = 				3;
+		static public const FLAG_CHAR:int = 			0;
+
+		// default flags
+		static public const DEFAULTFLAGS:int = 			65510;
+		static public const FORBIDDENWORD:int = 		65511;
+		static public const ONLYUPCASEFLAG:int = 		65511;
+
+		static public const MAXWORDLEN:int =			100;
+
+		static public const FLAG_NULL:int = 			0x00;
+		
+		// affentry options
+		static public const aeXPRODUCT:int =			(1 << 0);
+		
+		static public const SPELL_KEYSTRING:String = 	"qwertyuiop|asdfghjkl|zxcvbnm"; 
+
+		// internal const for ngram algorithm.
+	    public static const NGRAM_LOWERING:int = 		(1 << 2);
+		public static const NGRAM_LONGER_WORSE:int = 	(1 << 0);
+		public static const NGRAM_ANY_MISMATCH:int = 	(1 << 1);
+
+	    static public const MAX_ROOTS:int = 			100;
+	    static public const MAX_WORDS:int = 			100;
+	    static public const MAX_GUESS:int = 			200;
+	    static public const MAXNGRAMSUGS:int=			4;
+	    static public const MAXPHONSUGS:int=			2;
+
+		static public const DEFAULTENCODING:String = 	"utf-8";
+		
+		
+		static public const MAXSUGGESTION:int =			10;
+		// internal const for ICONV or OCONV RULE.
+		static public const CONV_ICONV:Boolean=			true;
+		static public const CONV_OCONV:Boolean=			false;
+		
+		//Maximum word breaks allowed
+		static public const MAX_WORD_BREAKS:int=		10;
+		
+		//Constants for Loading of Dictionaries in Parts
+		static public const DICT_LOAD_DELAY:int=		10; //this is timeout delay between loading of two parts of dictionaries. In milliseconds
+		static public const WORDS_PER_SPLIT:int=		20000;// this is the default value of number of words to be loaded in each split.
+		public function InternalConstants()
+		{
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as
new file mode 100644
index 0000000..239b031
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as
@@ -0,0 +1,39 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.error
+{
+	/*
+	 *@private
+	 * Deprecated class for now...
+	 * History: 
+	 *          In the beginning, I would like to have our own error class for critical exception. 
+	 *          After sharing this with Xie, I was convinced to drop this idea by discussing with Xie. 
+	 * ToDo: Need a revisit after we have compound word support.
+	 */
+	public class ContentError extends Error
+	{
+		public function ContentError(message:String, errorID:int)
+		{
+			super(message, errorID);
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as
new file mode 100644
index 0000000..d2dba8a
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as
@@ -0,0 +1,41 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.error
+{
+	/*
+	 *@private
+	 * Deprecated class for now...
+	 * History: 
+	 *          In the beginning, I would like to have our own error class for critical exception. 
+	 *          After sharing this with Xie, I was convinced to drop this idea by discussing with Xie. 
+	 * ToDo: Need a revisit after we have compound word support.
+	 */
+	public class ErrorTable
+	{
+		
+		static public const CONTENTPARSINGERROR_ID:int=11235;
+		static public const CONTENTPARSINGERROR_MSG:String="null cannot be parsed to a squiggly dictionary";
+		public function ErrorTable()
+		{
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as
new file mode 100644
index 0000000..52e5dd6
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as
@@ -0,0 +1,167 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging
+{
+	import flash.errors.IllegalOperationError;
+public class AbstractTarget implements ILoggingTarget
+{
+	private var _usingLevelMaskMode:Boolean;
+    public function AbstractTarget(usingLevelMaskMode:Boolean = false)
+    {
+        super();
+        this._usingLevelMaskMode = usingLevelMaskMode;
+
+//        _id = UIDUtil.createUID();
+    }
+
+    private var _loggerCount:uint = 0;
+
+    private var _filters:Array = [ "*" ];
+
+    public function get filters():Array
+    {
+        return _filters;
+    }
+
+    public function set filters(value:Array):void
+    {
+        if (value && value.length > 0)
+        {
+            // a valid filter value will be fully qualified or have a wildcard
+            // in it.  the wild card can only be located at the end of the
+            // expression.  valid examples  xx*, xx.*,  *
+            var filter:String;
+            var index:int;
+            var message:String;
+            for (var i:uint = 0; i<value.length; i++)
+            {
+                filter = value[i];
+                  // check for invalid characters
+                if (Log.hasIllegalCharacters(filter))
+                {
+                    throw new IllegalOperationError("Please check for invalid characters.");
+                }
+
+                index = filter.indexOf("*");
+                if ((index >= 0) && (index != (filter.length -1)))
+                {
+                    throw new IllegalOperationError("Please check for invalid filters.");
+                }
+            } // for
+        }
+        else
+        {
+            // if null was specified then default to all
+            value = ["*"];
+        }
+
+        if (_loggerCount > 0)
+        {
+            Log.removeTarget(this);
+            _filters = value;
+            Log.addTarget(this);
+        }
+        else
+        {
+            _filters = value;
+        }
+    }
+
+    private var _id:String;
+
+     public function get id():String
+     {
+         return _id;
+     }
+    
+    private var _level:int = LogEventLevel.ALL;
+
+    public function get level():int
+    {
+        return _level;
+    }
+
+    /**
+     *  @private
+     */
+    public function set level(value:int):void
+    {
+    	if ( this._usingLevelMaskMode == false ) {
+	    	if ( !LogEventLevel.isValidLevel(value) ) {
+	    		throw new IllegalOperationError("Please set an valid level in the level setter.");
+	    	}
+	    	
+	    	this._mask = LogEventLevel.getUpperMask(value);
+    	}else {
+	    	if ( !LogEventLevel.isValidMask(value) ) {
+	    		throw new IllegalOperationError("Please set an valid mask in the mask setter.");
+	    	}
+	    	this._mask = value;
+    	}
+        // A change of level may impact the target level for Log.
+        Log.removeTarget(this);
+        _level = value;
+        Log.addTarget(this);        
+    }
+    
+    
+    private var _mask:int = LogEventLevel.ALL;
+    public function get mask():int {
+    	return this._mask;
+    }
+    
+    
+    public function addLogger(logger:ILogger):void
+    {
+        if (logger)
+        {
+            _loggerCount++;
+            logger.addEventListener(LogEvent.eventID, logHandler);
+        }
+    }
+
+    public function removeLogger(logger:ILogger):void
+    {
+        if (logger)
+        {
+            _loggerCount--;
+            logger.removeEventListener(LogEvent.eventID, logHandler);
+        }
+    }
+
+    public function initialized(document:Object, id:String):void
+    {
+        _id = id;
+        Log.addTarget(this);
+    }
+
+    public function logEvent(event:LogEvent):void
+    {
+    }
+
+    private function logHandler(event:LogEvent):void
+    {
+        if ( (event.level & mask) != 0)
+            logEvent(event);
+    }
+}
+
+}


[11/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/TextEditor/src/TextEditor.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/TextEditor/src/TextEditor.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/TextEditor/src/TextEditor.mxml
new file mode 100644
index 0000000..7ce8942
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/TextEditor/src/TextEditor.mxml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following TextEditor MXML demonstrates how to use Squiggly API to check the block based text.
+* Note that the results from this example may differ based on dictionary file.
+* 
+* The following steps are taken:
+* <ol>
+*  <li>A <code>SpellingDictionary</code> object is created </li>
+*  <li>A <code>SpellChecker</code> object is created </li>
+*  <li>In the mx:application tag, add a function call to <code>init</code> for <code>applicationComplete</code> </li>
+*  <li>Create <code>init</code> function body: in the body, add an event listener for <code>SpellingDictionary</code> object. 
+* 		Then create a <code>URLRequest</code> object to specify the url of dictionary file. Then call the <code>SpellingDictionary</code> 
+*  	object <code>load</code> method to load the dictionary from disk or remote URL.</li>
+*  <li> Finish the <code>handleLoadComplete</code> function to attach the <code>SpellingDictionary</code> object to a <code>SpellChecker</code> object</li>
+*  <li> Use the regular expression to break the block text to word string. </li>
+*  <li> Add a function to call the <code>CheckWord</code> method of <code>SpellChecker</code> object to verify the correctness of a word. </li>
+*  <li> Use the <code>TextRange</code> to mark the mispelled word found by the last step. </li>
+*  <li>Add related MXML component tag and related property. </li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingEngine.swc) in your libs folder. Please see the reference "How to generate Squiggly dictionary".
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" horizontalAlign="left">
+<mx:Script>
+	<![CDATA[
+
+		import com.adobe.linguistics.spelling.*;
+		import mx.controls.textClasses.TextRange;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+			_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+			_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkText():void {
+			var wordPattern:RegExp =/\b\w+\b/; // match next word...
+			var inputValue:String = inputText.text;
+			var offset:int, curPos:int;
+			for ( ; ; ) {
+				var res:Array = inputValue.match( wordPattern); // lookup word by word....
+				if ( res == null ) break;
+				if ( !sp.checkWord(res[0]) ) {
+					offset = inputText.text.length-inputValue.length;
+					curPos = inputValue.indexOf(res[0]);
+					var currentRange:TextRange = new TextRange(inputText, false, offset+ curPos, offset+ curPos+res[0].length); // mark mispelled word.
+					currentRange.color = "red";
+				}
+				inputValue = inputValue.substr(inputValue.indexOf(res[0])+ res[0].length);
+			}
+		}
+		
+	]]>
+</mx:Script>
+	<mx:HBox>
+		<mx:Button id="check" label="Check Text" click="checkText()"  />
+	</mx:HBox>
+	<mx:TextArea id="inputText" height="100%" width="100%"/>	
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/HowToUseExamples.txt
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/HowToUseExamples.txt b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/HowToUseExamples.txt
new file mode 100644
index 0000000..eebe204
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/HowToUseExamples.txt
@@ -0,0 +1,33 @@
+<!--
+
+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.
+
+-->
+How to use Squiggly examples
+===================================
+
+To build and run an example, please follow these steps:
+
+1. Import the project into Flex Builder 3 or Flash Builder 4 beta.
+
+2. Copy the dictionary data (including the AdobeSpellingConfig.xml file and the dictionaries folder) from ../src to <project>/src folder. If you want to place the dictionary files in a different folder, please make sure the url is referred correctly in the code or in AdobeSpellingConfig.xml file.
+
+3. Copy the Squiggly lib(s) from ../libs to <project>/libs folder
+   - CheckWord, GetSuggestion, TextEditor needs only AdobeSpellingEngine.swc
+   - SquigglyUIExample, ContextMenuWithResource, CustomContextMenu needs both AdobeSpellingEngine.swc and AdobeSpellingUI.swc
+
+4. Build the project
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
new file mode 100644
index 0000000..e40772d
--- /dev/null
+++ b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/ITokenizer.as
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	/**
+	 * The <code>ITokenizer</code> Interface.
+	 * This interface defines default methods which will be used for Adobe Linguistic Service.
+	 * Be independent from any UI component or be able to adapt to a given UI component. 
+	 * Provide or define standardized way so that third-party can switch to their tokenizer.
+	 * Be able to use for any given language either by some kind of language specific handling or by some kind of unified logic for any given language.
+	 * More sophisticated implementations can be done for particular locales or environments in an application by implementing this interface.
+
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public interface ITokenizer
+	{
+		
+		/**
+		 * Return the first word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getFirstToken():Token;
+		
+		/**
+		 * Return the last word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getLastToken():Token;
+		
+		/**
+		 * Determine the next word following the current token.  
+		 * 
+		 * Return the token of the next word or <code>lastToken</code> object if all word have been returned.
+		 * @param token A <code>Token</code> object to be used for determining next word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getNextToken(token:Token):Token;
+		
+		/**
+		 * Determine the previous word preceding the current token.  
+		 * 
+		 * Return the token of the previous word or <code>firstToken</code> object if all word have been returned.
+		 * @param token A <code>Token</code> object to be used for determining previous word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		function getPreviousToken(token:Token):Token;
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
new file mode 100644
index 0000000..596481c
--- /dev/null
+++ b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
@@ -0,0 +1,393 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	import __AS3__.vec.Vector;
+	
+	import flash.utils.Dictionary;
+	
+    import flash.text.engine.TextBlock;
+    import flash.text.engine.TextElement;
+    import flash.text.engine.ElementFormat;
+
+		
+	/**
+	 * <p>The <code>TextTokenizer</code> class locates the boundaries of words in a 
+	 * block of text.</p>
+	 * 
+	 * Word boundary locations are found according to these general principles:
+	 * <ul>
+	 * 		<li> Be able to tokenize a block of text specified by start and end positions </li> 
+	 * 		<li> Default separator is Unicode white space character. Also break on newlines </li> 
+	 * 		<li> Tokens consist of either words or numbers in which case it may include commas, etc.. </li> 
+	 * 		<li> Apostrophes or hyphens within a word are kept with the word </li> 
+	 * 		<li> Punctuation, spaces and other characters that are not part of a token, are broken out separately </li> 
+	 * </ul>
+	 * <p>In the future versions, this class would also provide a way for the developers to customize the separators used by the tokenizer. </p>
+	 * 
+	 * @playerversion Flash 9.x
+ 	 * @langversion 3.0
+	*/
+	public class TextTokenizer implements ITokenizer
+	{
+		
+
+		private var _textBlock:TextBlock;
+		private var _textHolder:String;
+		private var _startIndex:int;
+		private var _endIndex:int;
+		private var _firstToken:Token;
+		private var _lastToken:Token;
+		
+		private var _ignoredCharactersDict:Dictionary = new Dictionary();
+
+
+		/**
+		 * The tokenizer for a String object.
+		 * This class implements the ITokenizer interface.
+		 * Constructs a new TextTokenizer object to break String to words by creating with a new piece of text. 
+		 * @param textHolder A <code>String</code> object to hold the text which will be processed by this tokenizer.
+		 * @param startIndex A <code>int</code> type input to hold the starting index of input text should be scanned.
+		 * @param endIndex A <code>int</code> type input to hold the ending index of input text should be scanned.
+		 * <span class="hide"> TODO param requestedLocaleIDName The LocaleID name to be used by this TextTokenizer object. </span>
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function TextTokenizer(textHolder:String, startIndex:int=0, endIndex:int=int.MAX_VALUE)//, requestedLocaleIDName:String=null)
+		{
+			//requestedLocaleIDName parameter is useful for potential extension. won't handle it in the first round of implementation.
+			//  same comments for API: requestedLocaleIDName()/actualLocaleIDName()/getAvailableLocaleIDNames()
+            var textElement:TextElement = new TextElement(textHolder, new ElementFormat()); 
+            var textBlock:TextBlock = new TextBlock();
+            textBlock.content = textElement; 
+			
+			/* init a tokenizer object */
+			this._textBlock = textBlock;
+			this._textHolder = textHolder;
+			this._startIndex =  0;
+			this._endIndex = this._textBlock.content.text.length;
+			initDefaultIgnoredCharacters();
+			setStartIndex(startIndex);
+			setEndIndex(endIndex);
+			
+		}
+		
+		private function setStartIndex(value:int):void {
+			if ( value <= 0 ) 
+				this._startIndex = 0;
+			else if ( value >= this._endIndex ) 
+				this._startIndex = this._endIndex;
+			else
+				this._startIndex=value;
+		}
+		
+		// strange behaviour with String.substring() function... need more thinking....
+		private function setEndIndex(value:int):void {
+			if ( value >= this._textBlock.content.text.length ) 
+				this._endIndex = this._textBlock.content.text.length;
+			else if ( value <= this._startIndex ) 
+				this._endIndex = this._startIndex;
+			else
+				this._endIndex = value;
+		}
+
+		private function initDefaultIgnoredCharacters():void {
+			var ignoredCharsArray:Array = [
+				0x002d,
+				0x2010
+			];
+			var ignoredChars:String = "";
+			for ( var i:int=0; i< ignoredCharsArray.length; ++i ) {
+				ignoredChars=ignoredChars+String.fromCharCode(ignoredCharsArray[i]);
+			}
+			this.ignoredCharacters = ignoredChars;
+		}
+
+		private function getNextTokenByIndex( startPos:int ):Token{
+			var resultToken:Token = null;
+			/* calculate first token and return it. */
+			var i:int = (startPos > this._startIndex) ? startPos: this._startIndex;
+			while ( i< this._endIndex ) {
+				var begin:int = i;
+				i = this._textBlock.findNextWordBoundary(begin);
+				var end:int = ( i <= this._endIndex) ? i : this._endIndex;
+				if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) {
+					resultToken = new Token(begin,end);
+					break;				
+				}
+			}
+			if ( resultToken==null ) resultToken = this.getLastToken();
+			return resultToken;
+		}
+		
+		private function getPreviousTokenByIndex( endPos:int):Token {
+			var resultToken:Token = null;
+			/* calculate first token and return it. */
+			var i:int = (endPos < this._endIndex) ? endPos: this._endIndex;
+			
+			/* special handling for last element in the word, bof */
+			var specialHandling:Boolean = false;
+			if ( i == this._endIndex ) {
+				specialHandling = true;
+				i = this._endIndex -1;
+			}
+			/* special handling for last element in the word, eof */
+			
+			while ( i > this._startIndex ) {
+				var end:int = i;
+				i = this._textBlock.findPreviousWordBoundary(end);
+				var begin:int = ( i > this._startIndex) ? i : this._startIndex;
+				
+				/* special handling for last element in the word, bof */
+				if ( specialHandling ) {
+					end = (this._textBlock.findNextWordBoundary(begin)<this._endIndex) ?this._textBlock.findNextWordBoundary(begin):this._endIndex;
+					specialHandling=false;
+					if ( (end != this._endIndex) && !isSingleSpecialCharacter(this._textHolder.substring(this._endIndex-1,this._endIndex)) ) {
+						begin = this._endIndex-1;
+						i=begin;
+						end = this._endIndex;
+					} 
+				}
+				/* special handling for last element in the word, eof */
+				
+				if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) {
+					resultToken = new Token(begin,end);
+					break;	
+				}
+			}
+			if ( resultToken==null ) resultToken = this.getFirstToken();
+			return resultToken;
+		}
+		
+		private function isExceptionCharacter(word:String):Boolean {
+			if ( word.length != 1 ) return false;
+			if ( this._ignoredCharactersDict[word] == true ) return true;
+			return false;
+		}
+		
+		private function getNextFilteredTokenByIndex(startPos:int):Token {
+			var token:Token = getNextTokenByIndex(startPos);
+			var firstToken:Token = token;
+			var cursor:int=token.last+1;
+			
+			while ( (cursor < this._endIndex) ) {
+				if ( !isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) {
+					break;
+				}else {
+					//another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior...
+					/*bof*/
+					while( cursor < this._endIndex && isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) {
+						cursor++;
+					}
+					cursor--;
+					/*eof*/
+				}
+				token = getNextTokenByIndex(cursor);
+				if ( token.first != cursor ) {
+					token = firstToken;
+					break;
+				}
+				token.first=firstToken.first;
+				firstToken = token;
+				cursor = token.last+1;
+			} 
+			return token;
+		}
+
+		private function getPreviousFilteredTokenByIndex(endPos:int):Token {
+			var token:Token = getPreviousTokenByIndex(endPos);
+			var lastToken:Token = token;
+			var cursor:int=token.first-1;
+			
+			while ( ( cursor > this._startIndex ) ) {
+				if ( !isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) {
+					break;
+				}else {
+					//another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior...
+					/*bof*/
+					while( cursor > this._startIndex && isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) {
+						cursor--;
+					}
+					cursor++;
+					/*eof*/
+				}
+				token = getPreviousTokenByIndex(cursor);
+				if ( token.last != cursor ) {
+					token = lastToken;
+					break;
+				}
+				token.last=lastToken.last;
+				lastToken = token;
+				cursor = token.first-1;
+			} 
+			return token;
+		}
+
+		private function isSingleSpecialCharacter(word:String):Boolean{
+			if ( word.length != 1 ) return false;
+			if ( word.toLocaleLowerCase() == word.toLocaleUpperCase() ) return true;
+			return false;
+		}
+		
+		/** 
+		 * Set all of ignored separators to this tokenizer class.
+		 * 
+		 * A vector of int containing all of ignored separators code point which are used by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set ignoredSeparators(characters:Vector.<int>):void {
+			if ( characters == null || characters.length==0 ) return;
+			this._ignoredCharactersDict = new Dictionary();
+			for ( var i:int =0;i<characters.length;++i) {
+				this._ignoredCharactersDict[String.fromCharCode(characters[i])]=true;
+			}
+		}
+		
+		/**
+		 * Get all of ignored separators used by this tokenizer class.
+		 * 
+		 * A vector of int containing all of ignored separators code point which are used by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get ignoredSeparators():Vector.<int>{
+			var result:Vector.<int> = new Vector.<int>();
+			for ( var key:String in _ignoredCharactersDict) {
+				result.push(key.charCodeAt(0) );
+			}
+			return result;
+			
+		}
+		
+		private function set ignoredCharacters(value:String ) :void {
+			if( value == null || value == "" ) return;
+			var charArr:Array = value.split("");
+			this._ignoredCharactersDict = new Dictionary();
+			for ( var i:int = 0;i< charArr.length;++i) {
+				this._ignoredCharactersDict[charArr[i]]=true;
+			}
+		}
+		
+		private function get ignoredCharacters():String {
+			var result:String = "";
+			for ( var key:String in _ignoredCharactersDict) {
+				result +=key;
+			}
+			return result;
+		}
+		
+		/**
+		 * The name of the requested locale ID that was passed to the constructor of this TextTokenizer object. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */	/*	
+		public function get requestedLocaleIDName():String {
+			return null;
+		}
+		
+		
+		/**
+		 * The name of the actual locale ID used by this TextTokenizer object. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */	/*	
+		public function get actualLocaleIDName():String {
+			return null;
+		}
+		
+		/**
+		 * Lists all of the locale ID names supported by this class.
+		 * 
+		 * A vector of strings containing all of the locale ID names supported by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		/*
+		public static function getAvailableLocaleIDNames():Vector.<String>{ return null;}
+*/
+		/**
+		 * Return the first word in the text being scanned. 
+		 * <p> NOTE: In a special case when there are no valid tokens in text, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> firstToken().first </code>equals int.MAX_VALUE and<code> firstToken().last </code>equals int.MAX_VALUE.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getFirstToken():Token {
+			
+			/* return the cached one. */
+			if ( this._firstToken != null )
+				return this._firstToken;
+			
+			/* calculate first token and return it. */
+			//this._firstToken = getNextTokenByIndex(this._startIndex); // without any filter from LS, directly use FTE tokenizer...
+			this._firstToken = getNextFilteredTokenByIndex(this._startIndex);
+
+			return this._firstToken;
+		}
+		
+		/**
+		 * @private
+		 * Return the last word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getLastToken():Token {
+			/* return the cached one. */
+			if ( this._lastToken != null )
+				return this._lastToken;
+				
+			/* calculate last token and return it. */
+			this._lastToken = new Token(int.MAX_VALUE,int.MAX_VALUE);
+			return this._lastToken;
+		}
+		
+		/**
+		 * Determine the next word following the current token.  
+		 * 
+		 * <p>Returns the token of the next word.</p><p> NOTE: When there are no more valid tokens, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> getNextToken().first </code>equals int.MAX_VALUE and<code> getNextToken().last </code>equals int.MAX_VALUE.</p>
+		 * @param token A <code>Token</code> object to be used for determining next word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getNextToken(token:Token):Token {
+			//return getNextTokenByIndex(token.last); // without any filter from LS, directly use FTE tokenizer...
+			return getNextFilteredTokenByIndex(token.last);
+		}
+		
+		/**
+		 * Determine the word preceding the current token.  
+		 * 
+		 * <p>Returns the token of the previous word or<code> getFirstToken </code>object if there is no preceding word.</p>
+		 * @param token A <code>Token</code> object to be used for determining previous word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getPreviousToken(token:Token):Token {
+			//return getPreviousTokenByIndex( token.first );// without any filter from LS, directly use FTE tokenizer...
+			return getPreviousFilteredTokenByIndex( token.first )
+		}
+
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
new file mode 100644
index 0000000..27fcfb2
--- /dev/null
+++ b/Squiggly/main/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
@@ -0,0 +1,94 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+	/**
+	 * A Token is an occurrence of a word in a block of text. It consists of the start and end offset of the word in the block of text.
+	 * The start and end offsets permit applications to re-associate a token with its source text, e.g., to display highlighted misspelled word in 
+	 * a block of text.
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public class Token
+	{
+		private var _first:uint;
+		private var _last:uint;
+		
+		/**
+		 * The Token class.
+		 * Constructs a Token with first and last offsets. . 
+		 * @param first A <code>int</code> type input to point start offset in the source text.
+		 * @param last A <code>int</code> type input to point end offset in the source text.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function Token(inFirst:int, inLast:int)
+		{
+			_first = inFirst;
+			_last = inLast;
+
+		}
+		
+		/**
+		 * Set the start offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set first(value:int):void {
+			_first=value;
+		}
+		
+		/**
+		 * Return the start offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get first():int
+		{
+			return _first;
+		}
+		
+		/**
+		 * Set the end offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set last(value:int):void {
+			_last = value;
+		}
+		
+		/**
+		 * Return the end offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get last():int
+		{
+			return _last;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as
new file mode 100644
index 0000000..7ec0312
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/HunspellDictionary.as
@@ -0,0 +1,205 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.LinguisticRule;
+	import com.adobe.linguistics.spelling.core.SquigglyDictionary;
+	import com.adobe.linguistics.spelling.core.utils.LinguisticRuleLoader;
+	import com.adobe.linguistics.spelling.core.utils.SquigglyDictionaryLoader;
+	
+	import flash.errors.IllegalOperationError;
+	import flash.events.ErrorEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IOErrorEvent;
+	import flash.events.SecurityErrorEvent;
+
+	/**
+	 *
+	 * This class enables creation and loading of spelling metadata including rules and dictionary data
+	 *
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 * @includeExample Examples/Air/CheckWord/src/CheckWord.mxml -noswf
+	 */
+	 
+	public final class HunspellDictionary extends EventDispatcher implements ISpellingDictionary
+	{
+		private var _dict:SquigglyDictionary;
+		private var _attrMgr:LinguisticRule;
+		private var _rulePath:String;
+		private var _dictionaryPath:String;
+		
+		private var ruleLoader:LinguisticRuleLoader = new LinguisticRuleLoader();
+		private var dictLoader:SquigglyDictionaryLoader = new SquigglyDictionaryLoader();
+
+		private var _loaded:Boolean;
+		
+		//adding vars for loading dictionaries in parts
+		private var _enableDictionarySplit:Boolean;
+		private var _wordsPerDictionarySplit:int;
+
+		/**
+		 * Constructs a new <code>HunspellDictionary</code> which can later be used by a <code>SpellChecker</code> object.
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function HunspellDictionary()
+		{
+			_attrMgr = null;
+			_dict = null;
+			_rulePath = null ;
+			_dictionaryPath = null;
+			_loaded = false;
+			//giving default values in case user does not want to specify these
+			_enableDictionarySplit =false;
+			_wordsPerDictionarySplit= 20000;
+
+		}
+
+		/**
+			@private
+			(This property is for Squiggly Developer use only.)
+		*/
+		public function get linguisticRule():LinguisticRule {
+			return _attrMgr;
+		}
+		
+		/**
+			@private
+			(This property is for Squiggly Developer use only.)
+		*/
+		public function get squigglyDictionary():SquigglyDictionary {
+			return  _dict;
+		}
+		
+		/**
+		 * Loads a Hunspell dictionary and corresponding rules files as specified by the <code>dictionaryURL</code> and the <code>rulesURL</code>.
+		 *
+		 * <p>The actual loading is done asynchronously and
+		 *	the <code>HunspellDictionary</code> object will dispatch an <code>Event.COMPLETE</code> event.
+		 *	When an error condition occurs, it will dispatch an <code>IOErrorEvent.IO_ERROR</code> event.</p>
+		 * @param rulesURL The URL of rule file to be loaded.
+		 * @param dictionaryURL The URL of Dictionary file to be loaded.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 * @example The following code shows how load API is called to load a Rule and Dictionary file to create a HunspellDictionay.
+		 * <listing version="3.0">
+		 * private var _newdict:HunspellDictionary = new HunspellDictionary();
+		 * _newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		 * </listing>
+		 */
+		public function load(rulesURL:String, dictionaryURL:String):void {
+			if ( rulesURL == null || dictionaryURL == null ) {
+				throw new IllegalOperationError("load function did not receive two valid URLs.");
+			}
+			_rulePath = rulesURL;
+			_dictionaryPath = dictionaryURL;
+			
+			ruleLoader.addEventListener(Event.COMPLETE,loadRuleComplete);
+			ruleLoader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+			ruleLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+			ruleLoader.load( _rulePath);
+			
+		}
+
+		/**
+		 * A flag that indicates if the dictionary has finished loading.
+		 * 
+		 * @return <code>true</code> if loading is completed. <code>false</code> if loading has not completed.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function get loaded():Boolean
+		{
+			return _loaded;
+		}
+
+		
+		// Private method to dispatch complete Event.
+		private function loadRuleComplete(evt:Event):void {
+			_attrMgr = ruleLoader.linguisticRule;
+			
+			dictLoader.linguisticRule = _attrMgr;
+			dictLoader.addEventListener(Event.COMPLETE,loadDictionaryComplete);
+			dictLoader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+			dictLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+			dictLoader.load(_dictionaryPath, _enableDictionarySplit, _wordsPerDictionarySplit);
+		}
+
+		// Private method to dispatch complete Event.
+		private function loadDictionaryComplete(evt:Event):void {
+			_dict = dictLoader.squigglyDictionary;
+			_loaded = true;
+			dispatchEvent(new Event(Event.COMPLETE));
+		}
+		
+		//Private method to dispatch an error event.
+		private function handleError(evt:Event):void {
+			bounceEvent(evt);
+		}
+		
+		private function bounceEvent(evt:Event):void {
+			dispatchEvent(evt.clone());
+		}
+		
+		/**
+		 * This is a flag that enables/disables loading of dictionary in splits.
+		 * By default this flag is set to <code>false</code>. In case the initial loading time of dictionaries is found slow, this flag should be set to <code>true</code>. By enabling this, squiggly will load dictionary in splits with each split having <code>wordsPerDictionarySplit</code> number of words.
+		 * <p>NOTE: This property, if used, should be set before calling <code>HunspellDictionary.load</code>. Once <code>HunspellDictionary.load</code> is called dictionaries will be loaded according to default values, and this property will not be used. </p>
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function get enableDictionarySplit():Boolean
+		{
+			return _enableDictionarySplit;	
+		}
+		
+		public function set enableDictionarySplit(enableDictionarySplit:Boolean):void
+		{
+			_enableDictionarySplit = enableDictionarySplit;
+		}
+		
+		/**
+		 * This property defines the number of words in one dictionary split.
+		 * By default the value of this property is set to 20000 words. This property is used only if <code>enableDictionarySplit</code> is set to <code>true</code>. If <code>enableDictionarySplit</code> is set to <code>flase</code> this property turns void.
+		 * <p>NOTE: This property, if used, should be defined before calling <code>HunspellDictionary.load</code>. Once <code>HunspellDictionary.load</code> is called dictionaries will be loaded according to default values, and this property will not be used. </p>
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function get wordsPerDictionarySplit():int
+		{
+			
+			return _wordsPerDictionarySplit;	
+		}
+		
+		public function set wordsPerDictionarySplit(wordsPerDictionarySplit:int):void
+		{
+			if(wordsPerDictionarySplit<=0){
+				//Do error Handling
+				throw new IllegalOperationError("wordsPerDictionarySplit should be a positive non-zero value.");
+			}
+			_wordsPerDictionarySplit = wordsPerDictionarySplit;
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as
new file mode 100644
index 0000000..34917bd
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellChecker.as
@@ -0,0 +1,62 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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
+{
+	/**
+	 * Interface for actual SpellChecker class implementations
+	 *
+	 * <p>If a new SpellChecker class is created, it must implement the methods and properties defined by this interface.
+	 * The <code>SpellChecker</code> class implements this interface.</p>
+	 * 
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public interface ISpellChecker
+	{	
+		/**
+		 * Spellchecks a word.
+		 * 
+		 * @param word	A string containing a word.
+		 * 			<p><strong>Note: </strong>Please be aware that it is the caller's responsibility to break down sentences into words that can be handled by this method.
+		 *  			For example, this method does not support punctuation marks such as comma, colon, quotes, etc.
+		 *				Punctuation marks should be stripped out from the word prior to calling this method.</p>
+		 * @return <code>true</code> if the word is properly spelled. <code>false</code> if the word is misspelled.
+		 *
+		 * @includeExample Examples/Flex/CheckWord/src/CheckWord.mxml
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		function checkWord(word:String):Boolean;
+		
+		/**
+		 * Gets suggestions for a misspelled word. 
+		 *
+		 * @param word	A string containing a misspelled word.
+		 * 					<p>A properly spelled word does not generate any suggestions.</p>  
+		 * @return	A list of suggestions.
+		 *					If the input word is properly spelled, an empty list will be returned.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		function getSuggestions(word:String):Array;
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as
new file mode 100644
index 0000000..8a46ef4
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/ISpellingDictionary.as
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.LinguisticRule;
+	import com.adobe.linguistics.spelling.core.SquigglyDictionary;
+	public interface ISpellingDictionary
+	{
+
+		/**
+		 * @private
+		 * (This property is for Squiggly Developer use only.)
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		function get linguisticRule():LinguisticRule;
+		
+		/**
+		 * @private
+		 * (This property is for Squiggly Developer use only.)
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		function get squigglyDictionary():SquigglyDictionary;
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as
new file mode 100644
index 0000000..bc23a91
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/SpellChecker.as
@@ -0,0 +1,387 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.*;
+
+	/**
+	 * The spelling engine.
+	 *
+	 * <p>This class implements the <code>ISpellChecker</code> interface.
+	 * This class performs spell&#x2d;checking and generates suggestion lists for misspelled words.
+	 * This class does not include any user-interface elements. Use this class if you want to offer 
+	 * control over how all upper case words are handled or words with numbers are handled, as this 
+	 * level of control is not offered by the SpellUI class.  However, please keep in mind that if 
+	 * you use this class, you will need to write your own UI.</p>
+	 *
+	 * <p>This class is based on the Hunspell algorithm and works with Hunspell/MySpell 
+	 * dictionaries and corresponding language rules files.</p>
+	 * <p>Currently, we support a subset of Hunspell rules(options). </p>
+	 * <p>The future of this class is to align as much as possible with existing Hunspell solution 
+	 * both for the algorithms and the content. </p> 
+	 * <p>In this version, users can also directly load Open-Office dictionaries to HunspellDictionary 
+	 * class and initialize a SpellChecker instance with this HunspellDictionary object. When using this 
+	 * class, the language of use is implied by the dictionary supplied.  Please make sure you load the 
+	 * appropriate dictionary based on the language the user selects to input.</p>
+	 * 
+	 * <p>Note: In the current implementation, only one main dictionary can be used at a time. In addition, 
+	 * in this version, suggestions for misspelled words do not include words from the user dictionary.</p>
+	 *
+	 * @includeExample Examples/Flex/TextEditor/src/TextEditor.mxml -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public class SpellChecker implements ISpellChecker
+	{
+		private var _spellingEngine:SquigglyEngine;
+		private var _rule:LinguisticRule;
+		private var _dict:SquigglyDictionary;
+		
+		private var _udEngine:UserDictionaryEngine;
+		
+		/**
+		 * Constructs a new <code>SpellChecker</code> object that performs language sensitive spell checking.
+		 * 
+		 * @param spellingDictionary A <code>ISpellingDictionary</code> interface to be used by this <code>SpellChecker</code>.
+		 * For example, you can pass a <code>HunspellDictonary</code> object which already implemented the <code>ISpellingDictionary</code> interface to this constructor.
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function SpellChecker(spellingDictionary:ISpellingDictionary)
+		{
+			_rule = spellingDictionary.linguisticRule;
+			_dict = spellingDictionary.squigglyDictionary;
+			_spellingEngine = new SquigglyEngine(_rule,_dict);
+			_spellingEngine.fastMode = true;
+			_udEngine = new UserDictionaryEngine();
+		}
+
+		/**
+		 * Add a user dictionary to the SpellChecker.
+		 * 
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation failed.
+		 * @param userDictionary A <code>UserDictionary</code> object to be added to this <code>SpellChecker</code>.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function addUserDictionary(userDictionary:UserDictionary):Boolean
+		{
+			return _udEngine.addDictionary(userDictionary.internalUserDictionary);
+		}
+		
+		/**
+		 * Remove a user dictionary from the SpellChecker.
+		 * 
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation failed.
+		 * @param userDictionary A <code>UserDictionary</code> object to be removed from this <code>SpellChecker</code>.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function removeUserDictionary(userDictionary:UserDictionary):Boolean
+		{
+			return _udEngine.removeDictionary(userDictionary.internalUserDictionary);
+		}
+
+		
+		/**
+		 * Spellchecks a word.
+		 * 
+		 * @param word	A string containing a word.
+		 * 			<p><strong>Notes:</strong></p>
+		 *				<ul>
+		 *					<li>
+		 *						Please be aware that it is the caller's responsibility to break down sentences into words that can be handled by this method.
+		 *  					For example, this method does not support punctuation marks such as comma, colon, quotes, etc.
+		 *						Punctuation marks should be stripped out from the word prior to calling this method.
+		 *						If a word contains white spaces (such as a regular space or non-breaking space), the word will be considered as misspelled.
+		 *					</li>
+		 *				</ul>
+		 * @return <code>true</code> if the word is properly spelled. <code>false</code> if the word is misspelled.
+		 *
+		 * @includeExample Examples/Flex/CheckWord/src/CheckWord.mxml -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function checkWord(word:String):Boolean
+		{
+			return (_spellingEngine==null)? false:(_udEngine.spell(word) || _spellingEngine.spell(word));
+		}
+		
+		/**
+		 * Gets suggestions for a misspelled word. 
+		 *
+		 * @param word	A string containing a misspelled word.
+		 * 	
+		 * @return	A list of suggestions. <p>Up to ten suggestions may be returned.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function getSuggestions(word:String):Array
+		{
+			return (_spellingEngine==null)? null:_spellingEngine.suggest(word);
+		}
+
+
+		/** @private
+		 * The version of this <code>SpellChecker</code> class.
+		 * 
+		 * <p>Example: "0.3"</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public static function get version():String
+		{
+			return "0.5";
+		}
+
+
+
+		/**
+		 * This property controls if Title Case Words should be considered as properly spelled.
+		 * 
+		 * <p>The default value is <code>false</code>.</p> 
+		 *
+		 * <p>If <code>ignoreTitleCase</code> is set to <code>true</code>, any words with first character capped are always considered as properly spelled.</p>
+		 * <p>If <code>ignoreWordWithTitleCase</code> is set to <code>true</code>, "Spel" will be considered as properly spelled even if the dictionary does not contain "spel" or "Spel".
+		 * If <code>ignoreWordWithTitleCase</code> is set to <code>false</code>, "Spel" will be considered as mispelled unless the dictionary contain "Spel".</p>
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		private function get ignoreWordWithTitleCase():Boolean
+		{
+			return _spellingEngine.ignoreCappedWord;
+		}
+		private function set ignoreWordWithTitleCase(value:Boolean):void
+		{
+			_spellingEngine.ignoreCappedWord = value;
+		}
+		
+		/**
+		 * This property controls if words in all upper case should be considered as properly spelled or not.
+		 * 
+		 * <table class="innertable">
+		 *		<tr>
+		 *			<td align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td>
+		 *			<td align="center"><strong>&#160;</strong></td>
+		 *			<td align="center"><strong>Description</strong></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>false</code></td>
+		 *			<td>Default</td>
+		 *			<td><p>Words with all characters in upper case are checked against the dictionary for proper spelling.</p>
+		 *				<p>Example: if <code>ignoreWordWithAllUpperCase = false</code>, "MISPEL" will be checked for proper spelling.</p></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>true</code></td>
+		 *			<td>&#160;</td>
+		 *			<td><p>Any words with all characters in upper case are always considered as properly spelled,
+		 *					no matter whether the word is in the dictionary or not.</p>
+		 *				<p>Example: if <code>ignoreWordWithAllUpperCase = true</code>, "MISPEL" will be considered as properly spelled.</p></td>
+		 *		</tr>
+		 *	</table>
+		 *
+		 *	<!--
+		 *	<p>Following table contains some examples to show how this property works.</p>
+		 * 	<p>Assumption: <code>ignoreWordWithTitleCase</code> = <code>false</code></p>
+		 *	<table class="innertable">
+		 *		<tr>
+		 *			<td rowspan=2 align="center"><strong>Word in dictionary</strong></td>
+		 *			<td rowspan=2 align="center"><strong>Input word</strong></td>
+		 *			<td colspan=2 align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td align="center"><strong><code>false</code></strong></td>
+		 *			<td align="center"><strong><code>true</code></strong></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td rowspan="4">apple</td>
+		 *			<td>apple</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>APPLE</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>Apple</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>aPPLe</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td rowspan="4">NATO</td>
+		 *			<td>nato</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>NATO</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>Nato</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>NaTo</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td rowspan="4">London</td>
+		 *			<td>london</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>LONDON</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>London</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>LoNDoN</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td rowspan="4">iPhone</td>
+		 *			<td>iphone</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>IPHONE</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>IPhone</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td>iPHoNe</td>
+		 *			<td>Properly spelled</td>
+		 *			<td>Properly spelled</td>
+		 *		</tr>
+		 *	</table>
+		 *	-->
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function get ignoreWordWithAllUpperCase():Boolean
+		{
+			return _spellingEngine.ignoreAllUpperCase;
+		}
+		public function set ignoreWordWithAllUpperCase(value:Boolean):void
+		{
+			_spellingEngine.ignoreAllUpperCase = value;
+		}
+		
+		
+		/**
+		 * This property controls if words with numbers, such as windows95, should be considered as properly spelled.
+		 * 
+		 * <table class="innertable">
+		 *		<tr>
+		 *			<td align="center"><strong><code>ignoreWordWithNumber</code></strong></td>
+		 *			<td align="center"><strong>&#160;</strong></td>
+		 *			<td align="center"><strong>Description</strong></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>false</code></td>
+		 *			<td>Default</td>
+		 *			<td><p>Any words containing digits are checked for proper spelling.</p>
+		 *				<p>Example: If <code>ignoreWordWithNumber</code> = <code>false</code>, "mispel99" will be checked for proper spelling.</p>
+		 *			</td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>true</code></td>
+		 *			<td>&#160;</td>
+		 *			<td><p>Words containing digits are always ignored/skipped regardless of the dictionary.</p>
+		 *				<p>Example: If <code>ignoreWordWithNumber</code> = <code>true</code>, "mispel99" will be considered as properly spelled.</p>
+		 *			</td>
+		 *		</tr>
+		 *	</table>
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function get ignoreWordWithNumber():Boolean 
+		{
+			return _spellingEngine.ignoreWordWithNumber;
+		}
+		public function set ignoreWordWithNumber(value:Boolean):void
+		{
+			_spellingEngine.ignoreWordWithNumber = value;
+		}
+
+
+		/**
+		 * <span class="hide">
+		 * TODO: Decide this block based API.
+		 * Check a block of text and find out all misspelled words in the text.
+		 * 
+		 * 
+		 * @param text	A string containing a block of texts.
+		 * @param separators	An array of separators.
+		 *
+		 * @return An Array of misspelled word tokens, each token contains the startIndex and length
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 * 
+		 * Option 1:
+		 *
+		 * public function checkText(text:String, separators:Array):Array
+		 * {
+		 * }
+		 * 
+		 * Option 2:
+		 *
+		 * public function checkText(text:String, tokenizer:ITokenizer):SpellResultIterator
+		 * {
+		 * }
+		 * </span>
+		 */
+	}
+}
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
new file mode 100644
index 0000000..d22f42c
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
@@ -0,0 +1,113 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 __AS3__.vec.Vector;
+	
+	import com.adobe.linguistics.spelling.UserDictionaryInternal;
+	/**
+	 * Represents a user dictionary.
+	 *
+	 * <p>This class represents a user dictionary that is used by the <code>SpellingService</code> class. This class itself is an in-memory object
+	 * and doesn't store persistent data. However, developers can import/export a <code>UserDictionary</code> object from/to a vector of String, 
+	 * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage:
+	 *
+	 * <ul>
+	 *	<li>SharedObject, which is used in our SpellingUI class to store words added from the ContextMenu</li>
+	 *	<li>File/FileStream, which is used in our UserDictionaryExample and can be shared across AIR applications</li>
+	 *	<li>Server side storage, for example database so that it can be shared across users</li>
+	 * </ul>
+	 * </p>
+	 * <p>If you are using our SpellingUI class the UserDictionary will be created behind the scene and stored in a SharedObject.</p>
+	 */	 
+	public class UserDictionary
+	{
+		private var _ud:UserDictionaryInternal;
+		
+		/**
+		 * @private
+		 */
+		public function get internalUserDictionary():UserDictionaryInternal
+		{
+			return _ud;
+		}
+		
+		/**
+		 * Constructs a new <code>UserDictionary</code> which can later be added to a <code>SpellingService</code> object.
+		 *
+		 * @param wordList A vector of words (String) to be added as the initial entries of this <code>UserDictionary</code>
+		 * @see UserDictionary.wordList
+		 *
+		 */
+		public function UserDictionary(wordList:Vector.<String>=null)
+		{
+			var array:Array = new Array();
+			if (wordList) {
+				for each (var w:String in wordList)
+					array.push(w);
+			}
+			
+			_ud = new UserDictionaryInternal(array);
+		}
+
+		/**
+		 * Add a word to the user dictionary.
+		 * 
+		 * @param word A word to be added to this <code>UserDictionary</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed, for example if the word is already added.
+		 * @see UserDictionary.removeWord()
+		 * 
+		 */		
+		public function addWord(word:String):Boolean	
+		{
+			return _ud.addWord(word);
+		}
+
+		/**
+		 * Removes a word from the user dicitonary.
+		 * 
+		 * @param word A word to be removed from this <code>UserDictionary</code>.
+		 * @return True if the operation was successful, false if the operation was failed, for example if the word doesn't exist in the dictionary.
+		 * @see UserDictionary.addWord()
+		 * 
+		 */		
+		public function removeWord(word:String):Boolean
+		{
+			return _ud.removeWord(word);
+		}
+
+		/**
+		 * All words in this user dictionary.
+		 *
+		 * @return A vector of String that contains all words in this user dictionary
+		 * 
+		 */		
+		public function get wordList():Vector.<String>
+		{
+			var result:Vector.<String> = new Vector.<String>();
+			var array:Array = _ud.wordList;
+			
+			for each (var w:String in array)
+				result.push(w);
+			
+			return result;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
new file mode 100644
index 0000000..d4034a8
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
@@ -0,0 +1,115 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils.WordList;
+	
+	/**
+	 * Represents a user dictionary.
+	 *
+	 * <p>This class represents a user dictionary that is used by the <code>SpellChecker</code> class. This class itself is an in-memory object
+	 * and doesn't store persistent data. However, developers can import/export a <code>UserDictionaryInternal</code> object from/to an Array of String, 
+	 * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage:
+	 *
+	 * <ul>
+	 *	<li>SharedObject, which is used in our SpellUI class to store words added from the ContextMenu</li>
+	 *	<li>File/FileStream, which is used in our UserDictionaryInternalExample and can be shared across AIR applications</li>
+	 *	<li>Server side storage, for example database so that it can be shared across users</li>
+	 * </ul>
+	 * </p>
+	 * <p>If you are using our SpellUI class the UserDictionaryInternal will be created behind the scene and stored in a SharedObject.</p>
+	 * @includeExample Examples/Air/UserDictionaryInternalExample/src/UserDictionaryInternalExample.mxml -noswf
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */	 
+	public class UserDictionaryInternal
+	{
+		/**
+		 @private
+		 (This property is for Squiggly Developer use only.)
+		 */
+		public var _wordList:WordList;
+		
+		/**
+		 * Constructs a new <code>UserDictionaryInternal</code> which can later be added to a <code>SpellChecker</code> object.
+		 *
+		 * @param wordList An array of words (String) to be added as the initial entries of this <code>UserDictionaryInternal</code>
+		 * @see UserDictionaryInternal.wordList
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function UserDictionaryInternal(wordList:Array=null)
+		{
+			// TODO: exception if has some problem with insert
+			_wordList= new WordList();
+			if (wordList) {
+				for each (var w:String in wordList)
+				_wordList.insert(w); 
+			}
+		}
+		
+		/**
+		 * Add a word to the user dictionary.
+		 * 
+		 * @param word A word to be added to this <code>UserDictionaryInternal</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed.
+		 * @see UserDictionaryInternal.removeWord()
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function addWord(word:String):Boolean	
+		{
+			return _wordList.insert(word);
+		}
+		
+		/**
+		 * Removes a word from the user dicitonary.
+		 * 
+		 * @param word A word to be removed from this <code>UserDictionaryInternal</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed.
+		 * @see UserDictionaryInternal.addWord()
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function removeWord(word:String):Boolean
+		{
+			return _wordList.remove(word);
+		}
+		
+		/**
+		 * List of all words in this user dictionary.
+		 *
+		 * @return An Array of String that contains all words in this user dictionary
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get wordList():Array
+		{
+			// TODO: make sure no return by reference
+			return _wordList.toArray();
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as
new file mode 100644
index 0000000..cef5b0d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/DictionaryManager.as
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	import com.adobe.linguistics.spelling.core.container.HashTable;
+	public class DictionaryManager
+	{
+		private var _table:Array;
+		public function DictionaryManager()
+		{
+			_table = new Array();
+		}
+		
+		public function addDictionary(dict:SquigglyDictionary):Boolean {
+			if ( dict == null ) return false;
+			for ( var i:int = 0; i< _table.length; ++i ) {
+				if ( dict == _table[i] )
+					return false;
+			}
+			_table.push(dict);
+			return true;
+		}
+		
+		public function removeDictionary(dict:SquigglyDictionary):Boolean {
+			if ( dict == null) return false;
+			for ( var i:int = 0; i< _table.length; ++i ) {
+				if ( dict == _table[i] ) {
+					_table = _table.slice(i,1); // remove dictionary from the table.
+				}
+			}
+			return true;
+			
+		}
+		
+		public function get dictonaryList():Array {
+			return this._table;
+		}
+		
+		public function isEmpty():Boolean {
+			return (this._table == null ) ? true : false;
+		}
+		
+		public function get size():int {
+			return this._table.length;
+		}
+		
+		public function lookup( word:String ) :HashEntry {
+			for ( var i:int = 0; i < _table.length; ++i ) {
+				if ( _table[i].containsKey(word) )
+					return _table[i].getElement(word);
+			}
+			return null;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as
new file mode 100644
index 0000000..64ac685
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/HashEntry.as
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	import com.adobe.linguistics.spelling.core.utils.StringUtils;
+	public class HashEntry
+	{
+		private var _affStr:String; // affix flag vector
+		private var _nextEntry:HashEntry;
+		
+		// Not sure now..just leave it here.
+		private var _variableFields:String;   // variable fields (only for special pronounciation yet)
+		
+		
+		public function HashEntry(affStr:String=null,desc:String = null)
+		{
+			this._affStr = StringUtils.sort(affStr);
+			this._variableFields = desc;
+			this._nextEntry = null;
+		}
+		
+		public function addEntry(affStr:String=null,desc:String = null):Boolean {
+			if ( this._nextEntry != null ) return false;
+			this._nextEntry = new HashEntry(affStr, desc);
+			return true;
+		}
+		
+		public function get next():HashEntry {
+			return this._nextEntry;
+		}
+		
+		public function get affixFlagVector():String {
+			return this._affStr;
+		}
+		
+		public function set affixFlagVector(affStr:String):void {
+			this._affStr = StringUtils.sort(affStr);
+		}
+		
+		public function get variableFields():String {
+			return this._variableFields;
+		}
+		
+		public function set variableFields( varF:String) :void {
+			this._variableFields = varF;
+		}
+		
+		public function testAffix(flag:Number):Boolean {
+			if ( this._affStr == null ) return false;
+			var mid:int, left:int=0, right:int= this._affStr.length - 1;
+			while ( left <= right ) {
+				mid = (right+left)/2;
+				if ( this._affStr.charCodeAt(mid) == flag )
+					return true;
+				if ( flag < this._affStr.charCodeAt(mid) ) right = mid -1;
+				else left = mid + 1;
+			}
+			return false;
+		}
+
+		public function testAffixs(flags:Array):Boolean {
+			for ( var i:int; i< flags.length; ++i) {
+				if( testAffix(flags[i]) )
+					return true;
+			}
+			return false;
+		}
+		//For develepors only, this function is made so that when flagmode=flag_long flags can be viewed.
+		public function printFlag(flag:Number):void{
+			var result:String =  String.fromCharCode(flag>>8) + String.fromCharCode(flag-((flag>>8)<<8));
+			
+		}
+
+		
+		static public function TESTAFF(affix:String, flag:Number):Boolean {
+			if ( affix == null ) return false;
+			affix =  StringUtils.sort(affix);
+			var mid:int, left:int=0, right:int= affix.length - 1;
+			while ( left <= right ) {
+				mid = (right+left)/2;
+				if ( affix.charCodeAt(mid) == flag )
+					return true;
+				if ( flag < affix.charCodeAt(mid) ) right = mid -1;
+				else left = mid + 1;
+			}
+			return false;
+			
+		}
+	}
+}
\ No newline at end of file


[02/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/Data/usa.txt
----------------------------------------------------------------------
diff --git a/Squiggly/main/Data/usa.txt b/Squiggly/main/Data/usa.txt
new file mode 100644
index 0000000..4be12de
--- /dev/null
+++ b/Squiggly/main/Data/usa.txt
@@ -0,0 +1,97812 @@
+
+A
+A's
+ABC
+ABC's
+AC
+ACT
+AFAIK
+AFAIKs
+AI
+AIDS
+AIDSes
+AIs
+AM
+ANSI
+ANSIs
+AOL
+AOL's
+ASAP
+ASCII
+ASCIIs
+ATM
+AV
+AWOL
+Aachen
+Aachen's
+Aaliyah
+Aaliyah's
+Aaron
+Aaron's
+Abbas
+Abbasid
+Abbasid's
+Abbott
+Abbott's
+Abby
+Abby's
+Abdul
+Abdul's
+Abe
+Abe's
+Abel
+Abel's
+Abelard
+Abelard's
+Abelson
+Abelson's
+Aberdeen
+Aberdeen's
+Abernathy
+Abernathy's
+Abidjan
+Abidjan's
+Abigail
+Abigail's
+Abilene
+Abilene's
+Abner
+Abner's
+Abraham
+Abraham's
+Abram
+Abram's
+Abrams
+Absalom
+Absalom's
+Abuja
+Abyssinia
+Abyssinia's
+Abyssinian
+Ac
+Ac's
+Acadia
+Acadia's
+Acapulco
+Acapulco's
+Accra
+Accra's
+Acevedo
+Acevedo's
+Achaean
+Achaean's
+Achebe
+Achebe's
+Achernar
+Achernar's
+Acheson
+Acheson's
+Achilles
+Aconcagua
+Aconcagua's
+Acosta
+Acosta's
+Acropolis
+Acropolis's
+Acrux
+Acrux's
+Actaeon
+Actaeon's
+Acton
+Acton's
+Acts
+Acuff
+Acuff's
+Ada
+Ada's
+Adam
+Adam's
+Adams
+Adan
+Adan's
+Adana
+Adana's
+Adar
+Adar's
+Adas
+Addams
+Adderley
+Adderley's
+Addie
+Addie's
+Addison
+Addison's
+Adela
+Adela's
+Adelaide
+Adelaide's
+Adele
+Adele's
+Adeline
+Adeline's
+Aden
+Aden's
+Adenauer
+Adenauer's
+Adhara
+Adhara's
+Adidas
+Adidas's
+Adirondack
+Adirondack's
+Adirondacks
+Adkins
+Adkins's
+Adler
+Adler's
+Adolf
+Adolf's
+Adolfo
+Adolfo's
+Adolph
+Adolph's
+Adonis
+Adonis's
+Adonises
+Adrian
+Adrian's
+Adriana
+Adriana's
+Adriatic
+Adrienne
+Adrienne's
+Advent
+Advent's
+Adventist
+Adventist's
+Advents
+Advil
+Advil's
+Aegean
+Aelfric
+Aelfric's
+Aeneas
+Aeneid
+Aeneid's
+Aeolus
+Aeolus's
+Aeroflot
+Aeroflot's
+Aeschylus
+Aeschylus's
+Aesculapius
+Aesculapius's
+Aesop
+Aesop's
+Afghan
+Afghan's
+Afghanistan
+Afghanistan's
+Afghans
+Africa
+Africa's
+African
+Africans
+Afrikaans
+Afrikaans's
+Afrikaner
+Afrikaner's
+Afrikaners
+Afro
+Afro's
+Afrocentrism
+Afros
+Ag
+Ag's
+Agamemnon
+Agamemnon's
+Agassi
+Agassi's
+Agassiz
+Agassiz's
+Agatha
+Agatha's
+Aggie
+Aggie's
+Aglaia
+Aglaia's
+Agnes
+Agnes's
+Agnew
+Agnew's
+Agni
+Agni's
+Agra
+Agra's
+Agricola
+Agricola's
+Agrippa
+Agrippa's
+Agrippina
+Agrippina's
+Aguilar
+Aguilar's
+Aguinaldo
+Aguinaldo's
+Aguirre
+Aguirre's
+Agustin
+Agustin's
+Ahab
+Ahab's
+Ahmad
+Ahmad's
+Ahmadabad
+Ahmed
+Ahmed's
+Ahriman
+Ahriman's
+Aida
+Aida's
+Aiken
+Aiken's
+Aileen
+Aileen's
+Aimee
+Aimee's
+Ainu
+Ainu's
+Airedale
+Airedale's
+Airedales
+Aisha
+Aisha's
+Ajax
+Ajax's
+Akbar
+Akbar's
+Akhmatova
+Akhmatova's
+Akihito
+Akihito's
+Akita
+Akita's
+Akkad
+Akkad's
+Akron
+Akron's
+Al
+Al's
+Ala
+Ala's
+Alabama
+Alabama's
+Alabaman
+Alabamans
+Alabamian
+Alabamians
+Aladdin
+Aladdin's
+Alamo
+Alamo's
+Alamogordo
+Alamogordo's
+Alan
+Alan's
+Alana
+Alana's
+Alar
+Alaric
+Alaric's
+Alaska
+Alaska's
+Alaskan
+Alaskans
+Alba
+Alba's
+Albania
+Albania's
+Albanian
+Albanian's
+Albanians
+Albany
+Albany's
+Albee
+Albee's
+Alberio
+Alberio's
+Albert
+Albert's
+Alberta
+Alberta's
+Alberto
+Alberto's
+Albigensian
+Albion
+Albion's
+Albireo
+Albireo's
+Albuquerque
+Albuquerque's
+Alcatraz
+Alcatraz's
+Alcestis
+Alcestis's
+Alcibiades
+Alcibiades's
+Alcmena
+Alcmena's
+Alcoa
+Alcoa's
+Alcott
+Alcott's
+Alcuin
+Alcuin's
+Alcyone
+Alcyone's
+Aldan
+Aldan's
+Aldebaran
+Aldebaran's
+Alden
+Alden's
+Alderamin
+Alderamin's
+Aldo
+Aldo's
+Aldrin
+Aldrin's
+Alec
+Alec's
+Aleichem
+Aleichem's
+Alejandra
+Alejandra's
+Alejandro
+Alejandro's
+Alembert
+Alembert's
+Aleppo
+Aleppo's
+Aleut
+Aleut's
+Aleutian
+Alex
+Alex's
+Alexander
+Alexander's
+Alexandra
+Alexandra's
+Alexandria
+Alexandria's
+Alexei
+Alexei's
+Alexis
+Alfonso
+Alfonso's
+Alfonzo
+Alfonzo's
+Alford
+Alford's
+Alfred
+Alfred's
+Alfreda
+Alfreda's
+Alfredo
+Alfredo's
+Algenib
+Algenib's
+Alger
+Alger's
+Algeria
+Algeria's
+Algerian
+Algerians
+Algieba
+Algieba's
+Algiers
+Algiers's
+Algol
+Algol's
+Algonquian
+Algonquian's
+Algonquians
+Algonquin
+Algonquin's
+Alhambra
+Alhambra's
+Alhena
+Alhena's
+Ali
+Ali's
+Alice
+Alice's
+Alicia
+Alicia's
+Alighieri
+Alighieri's
+Aline
+Aline's
+Alioth
+Alioth's
+Alisa
+Alisa's
+Alisha
+Alisha's
+Alison
+Alison's
+Alissa
+Alissa's
+Alistair
+Alistair's
+Alkaid
+Alkaid's
+Allah
+Allah's
+Allahabad
+Allahabad's
+Allan
+Allan's
+Alleghenies
+Allegheny
+Allegheny's
+Allegra
+Allegra's
+Allen
+Allen's
+Allende
+Allende's
+Allentown
+Allentown's
+Allie
+Allie's
+Allison
+Allison's
+Allstate
+Allstate's
+Allyson
+Allyson's
+Alma
+Alma's
+Almach
+Almach's
+Almaty
+Almighty
+Almighty's
+Almohad
+Almohad's
+Almoravid
+Almoravid's
+Alnilam
+Alnilam's
+Alnitak
+Alnitak's
+Alonzo
+Alonzo's
+Alpert
+Alpert's
+Alphard
+Alphard's
+Alphecca
+Alphecca's
+Alpheratz
+Alpheratz's
+Alphonse
+Alphonse's
+Alphonso
+Alphonso's
+Alpine
+Alpo
+Alpo's
+Alps
+Alsace
+Alsace's
+Alsatian
+Alsatian's
+Alsop
+Alsop's
+Alston
+Alston's
+Alta
+Alta's
+Altai
+Altai's
+Altaic
+Altaic's
+Altair
+Altair's
+Altamira
+Altamira's
+Althea
+Althea's
+Altiplano
+Altiplano's
+Altman
+Altman's
+Altoids
+Altoids's
+Alton
+Alton's
+Aludra
+Aludra's
+Alva
+Alva's
+Alvarado
+Alvarado's
+Alvarez
+Alvarez's
+Alvaro
+Alvaro's
+Alvin
+Alvin's
+Alyce
+Alyce's
+Alyson
+Alyson's
+Alyssa
+Alyssa's
+Alzheimer
+Alzheimer's
+Am
+Am's
+Amadeus
+Amadeus's
+Amado
+Amado's
+Amalia
+Amalia's
+Amanda
+Amanda's
+Amarillo
+Amarillo's
+Amaru
+Amaru's
+Amaterasu
+Amaterasu's
+Amati
+Amati's
+Amazon
+Amazon's
+Amazons
+Amber
+Amber's
+Amelia
+Amelia's
+Amenhotep
+Amenhotep's
+Amerasian
+Amerasians
+America
+America's
+American
+Americana
+Americana's
+Americanism
+Americanism's
+Americanisms
+Americanization
+Americanization's
+Americanizations
+Americanize
+Americanized
+Americanizes
+Americanizing
+Americans
+Americas
+Amerind
+Amerind's
+Amerindian
+Amerindian's
+Amerindians
+Amerinds
+Ameslan
+Ameslan's
+Amharic
+Amharic's
+Amherst
+Amherst's
+Amie
+Amie's
+Amiga
+Amiga's
+Amish
+Amman
+Amman's
+Amoco
+Amoco's
+Amos
+Amparo
+Amparo's
+Ampere
+Ampere's
+Amritsar
+Amritsar's
+Amsterdam
+Amsterdam's
+Amtrak
+Amundsen
+Amundsen's
+Amur
+Amur's
+Amway
+Amway's
+Amy
+Amy's
+Ana
+Ana's
+Anabaptist
+Anabaptist's
+Anabel
+Anabel's
+Anacin
+Anacin's
+Anacreon
+Anacreon's
+Anaheim
+Anaheim's
+Analects
+Analects's
+Ananias
+Ananias's
+Anasazi
+Anasazi's
+Anastasia
+Anastasia's
+Anatole
+Anatole's
+Anatolia
+Anatolia's
+Anatolian
+Anaxagoras
+Anaxagoras's
+Anchorage
+Anchorage's
+Andalusia
+Andalusia's
+Andalusian
+Andaman
+Andean
+Andersen
+Andersen's
+Anderson
+Anderson's
+Andes
+Andorra
+Andorra's
+Andre
+Andre's
+Andrea
+Andrea's
+Andrei
+Andrei's
+Andres
+Andrew
+Andrew's
+Andrews
+Andrianampoinimerina
+Andrianampoinimerina's
+Andromache
+Andromache's
+Andromeda
+Andromeda's
+Andropov
+Andy
+Andy's
+Angara
+Angara's
+Angel
+Angel's
+Angela
+Angela's
+Angelia
+Angelia's
+Angelica
+Angelica's
+Angelico
+Angelico's
+Angelina
+Angelina's
+Angeline
+Angeline's
+Angelique
+Angelique's
+Angelita
+Angelita's
+Angelo
+Angelo's
+Angelou
+Angevin
+Angevin's
+Angie
+Angie's
+Angkor
+Angkor's
+Anglia
+Anglia's
+Anglican
+Anglicanism
+Anglicanism's
+Anglicanisms
+Anglicans
+Anglicize
+Anglicized
+Anglicizes
+Anglicizing
+Anglo
+Anglo's
+Anglophile
+Anglophile's
+Anglophiles
+Anglos
+Angola
+Angola's
+Angolan
+Angolans
+Angora
+Angora's
+Angoras
+Anguilla
+Anguilla's
+Angus
+Angus's
+Aniakchak
+Aniakchak's
+Anibal
+Anibal's
+Anita
+Anita's
+Ankara
+Ankara's
+Ann
+Ann's
+Anna
+Anna's
+Annabel
+Annabel's
+Annabelle
+Annabelle's
+Annam
+Annam's
+Annapolis
+Annapolis's
+Annapurna
+Annapurna's
+Anne
+Anne's
+Annette
+Annette's
+Annie
+Annie's
+Annmarie
+Annmarie's
+Anouilh
+Anouilh's
+Anselm
+Anselm's
+Anselmo
+Anselmo's
+Anshan
+Anshan's
+Antaeus
+Antaeus's
+Antananarivo
+Antananarivo's
+Antarctic
+Antarctic's
+Antarctica
+Antarctica's
+Antares
+Anthony
+Anthony's
+Antichrist
+Antichrist's
+Antichrists
+Antietam
+Antietam's
+Antigone
+Antigone's
+Antigua
+Antigua's
+Antilles
+Antioch
+Antioch's
+Antipas
+Antipas's
+Antofagasta
+Antofagasta's
+Antoine
+Antoine's
+Antoinette
+Antoinette's
+Anton
+Anton's
+Antone
+Antone's
+Antonia
+Antonia's
+Antoninus
+Antoninus's
+Antonio
+Antonio's
+Antonius
+Antonius's
+Antony
+Antony's
+Antwan
+Antwan's
+Antwerp
+Antwerp's
+Anubis
+Anubis's
+Anzac
+Anzac's
+Apache
+Apache's
+Apaches
+Apalachicola
+Apalachicola's
+Apennines
+Aphrodite
+Aphrodite's
+Apia
+Apia's
+Apocrypha
+Apocrypha's
+Apollinaire
+Apollinaire's
+Apollo
+Apollo's
+Apollonian
+Apollos
+Appalachia
+Appalachia's
+Appalachian
+Appalachians
+Appaloosa
+Appaloosa's
+Apple
+Apple's
+Appleseed
+Appleseed's
+Appleton
+Appleton's
+Appomattox
+Appomattox's
+Apr
+Apr's
+April
+April's
+Aprils
+Apuleius
+Apuleius's
+Aquafresh
+Aquafresh's
+Aquarius
+Aquarius's
+Aquariuses
+Aquila
+Aquila's
+Aquinas
+Aquinas's
+Aquino
+Aquino's
+Aquitaine
+Aquitaine's
+Ar
+Ar's
+Ara
+Ara's
+Arab
+Arab's
+Arabia
+Arabia's
+Arabian
+Arabians
+Arabic
+Arabic's
+Arabs
+Araby
+Araby's
+Araceli
+Araceli's
+Arafat
+Arafat's
+Araguaya
+Araguaya's
+Aral
+Aral's
+Aramaic
+Aramaic's
+Aramco
+Aramco's
+Arapaho
+Arapaho's
+Ararat
+Ararat's
+Araucanian
+Araucanian's
+Arawak
+Arawak's
+Arawakan
+Arawakan's
+Arbitron
+Arbitron's
+Arcadia
+Arcadia's
+Arcadian
+Archean
+Archibald
+Archibald's
+Archie
+Archie's
+Archimedes
+Archimedes's
+Arctic
+Arctic's
+Arcturus
+Arcturus's
+Arden
+Arden's
+Arequipa
+Arequipa's
+Ares
+Argentina
+Argentina's
+Argentine
+Argentine's
+Argentines
+Argentinian
+Argentinians
+Argo
+Argo's
+Argonaut
+Argonaut's
+Argonne
+Argonne's
+Argos
+Argus
+Argus's
+Ariadne
+Ariadne's
+Arianism
+Arianism's
+Ariel
+Ariel's
+Aries
+Arieses
+Ariosto
+Ariosto's
+Aristarchus
+Aristarchus's
+Aristides
+Aristophanes
+Aristophanes's
+Aristotelian
+Aristotle
+Aristotle's
+Arius
+Arius's
+Ariz
+Ariz's
+Arizona
+Arizona's
+Arizonan
+Arizonans
+Arizonian
+Arizonians
+Arjuna
+Arjuna's
+Ark
+Ark's
+Arkansan
+Arkansan's
+Arkansas
+Arkansas's
+Arkhangelsk
+Arkhangelsk's
+Arkwright
+Arkwright's
+Arlene
+Arlene's
+Arline
+Arline's
+Arlington
+Arlington's
+Armageddon
+Armageddon's
+Armageddons
+Armagnac
+Armagnac's
+Armand
+Armand's
+Armando
+Armando's
+Armani
+Armani's
+Armenia
+Armenia's
+Armenian
+Armenian's
+Armenians
+Arminius
+Arminius's
+Armonk
+Armonk's
+Armour
+Armour's
+Armstrong
+Armstrong's
+Arneb
+Arneb's
+Arnhem
+Arnhem's
+Arno
+Arno's
+Arnold
+Arnold's
+Arnulfo
+Arnulfo's
+Aron
+Aron's
+Arrhenius
+Arrhenius's
+Arron
+Arron's
+Art
+Art's
+Artaxerxes
+Artaxerxes's
+Artemis
+Artemis's
+Arthur
+Arthur's
+Arthurian
+Artie
+Artie's
+Arturo
+Arturo's
+Aruba
+Aruba's
+Aryan
+Aryan's
+Aryans
+As
+Asama
+Asama's
+Ascella
+Ascella's
+Asgard
+Asgard's
+Ashanti
+Ashanti's
+Ashcroft
+Ashcroft's
+Ashe
+Ashe's
+Ashikaga
+Ashikaga's
+Ashkenazim
+Ashkhabad
+Ashkhabad's
+Ashlee
+Ashlee's
+Ashley
+Ashley's
+Ashmolean
+Ashmolean's
+Ashurbanipal
+Ashurbanipal's
+Asia
+Asia's
+Asian
+Asians
+Asiatic
+Asiatic's
+Asiatics
+Asimov
+Asmara
+Asmara's
+Asoka
+Asoka's
+Aspell
+Aspell's
+Aspen
+Aspen's
+Aspidiske
+Aspidiske's
+Asquith
+Asquith's
+Assad
+Assad's
+Assam
+Assam's
+Assamese
+Assamese's
+Assisi
+Assisi's
+Assyria
+Assyria's
+Assyrian
+Assyrian's
+Assyrians
+Astaire
+Astaire's
+Astana
+Astana's
+Astarte
+Astarte's
+Aston
+Aston's
+Astor
+Astor's
+Astoria
+Astoria's
+Astrakhan
+Astrakhan's
+AstroTurf
+AstroTurfs
+Asturias
+Asturias's
+Asunci�n
+Asunci�n's
+Aswan
+Aswan's
+At
+At's
+Atacama
+Atacama's
+Atahualpa
+Atahualpa's
+Atalanta
+Atalanta's
+Atari
+Atari's
+Atat�rk
+Atat�rk's
+Athabasca
+Athabasca's
+Athabascan's
+Athena
+Athena's
+Athenian
+Athenian's
+Athenians
+Athens
+Athens's
+Atkins
+Atkins's
+Atkinson
+Atkinson's
+Atlanta
+Atlanta's
+Atlantes
+Atlantic
+Atlantic's
+Atlantis
+Atlantis's
+Atlas
+Atlas's
+Atlases
+Atman
+Atreus
+Atreus's
+Atria
+Atria's
+Atropos
+Atropos's
+Ats
+Attic
+Attica
+Attica's
+Attila
+Attila's
+Attlee
+Attlee's
+Attucks
+Atwood
+Atwood's
+Au
+Au's
+Aubrey
+Aubrey's
+Auckland
+Auckland's
+Auden
+Auden's
+Audi
+Audi's
+Audion
+Audion's
+Audra
+Audra's
+Audrey
+Audrey's
+Audubon
+Audubon's
+Aug
+Aug's
+Augean
+Augsburg
+Augsburg's
+August
+August's
+Augusta
+Augusta's
+Augustan
+Augustine
+Augustine's
+Augusts
+Augustus
+Augustus's
+Aurangzeb
+Aurangzeb's
+Aurelia
+Aurelia's
+Aurelio
+Aurelio's
+Aurelius
+Aurelius's
+Aureomycin
+Aureomycin's
+Auriga
+Auriga's
+Aurora
+Aurora's
+Auschwitz
+Auschwitz's
+Aussie
+Aussie's
+Aussies
+Austen
+Austen's
+Austerlitz
+Austerlitz's
+Austin
+Austin's
+Austins
+Australasia
+Australasia's
+Australia
+Australia's
+Australian
+Australian's
+Australians
+Australoid
+Australopithecus
+Australopithecus's
+Austria
+Austria's
+Austrian
+Austrians
+Austronesian
+Autumn
+Autumn's
+Av
+Av's
+Ava
+Ava's
+Avalon
+Avalon's
+Ave
+Ave's
+Aventine
+Aventine's
+Avernus
+Avernus's
+Averroes
+Averroes's
+Avery
+Avery's
+Aves
+Avesta
+Avesta's
+Avicenna
+Avicenna's
+Avignon
+Avignon's
+Avila
+Avila's
+Avior
+Avior's
+Avis
+Avogadro
+Avogadro's
+Avon
+Avon's
+Axum
+Axum's
+Ayala
+Ayala's
+Ayers
+Aymara
+Aymara's
+Ayrshire
+Ayrshire's
+Ayurveda
+Ayurveda's
+Ayyubid
+Ayyubid's
+Azana
+Azana's
+Azania
+Azania's
+Azazel
+Azazel's
+Azerbaijan
+Azerbaijan's
+Azerbaijani
+Azerbaijani's
+Azores
+Azov
+Azov's
+Aztec
+Aztec's
+Aztecan
+Aztecs
+Aztlan
+Aztlan's
+B
+B's
+BASIC
+BASICs
+BBQ
+BBS
+BBSes
+BITNET
+BITNETs
+BLT
+BLTs
+BMW
+BMW's
+BS
+BSD
+BSDs
+Ba
+Ba's
+Baal
+Baal's
+Babar's
+Babbage
+Babbage's
+Babbitt
+Babbitt's
+Babel
+Babel's
+Babels
+Babur's
+Babylon
+Babylon's
+Babylonian
+Babylonian's
+Babylons
+Bacall
+Bacall's
+Bacardi
+Bacardi's
+Bacchanalia
+Bacchanalia's
+Bacchus
+Bacchus's
+Bach
+Bach's
+Backus
+Backus's
+Bacon
+Bacon's
+Bactria
+Bactria's
+Baden
+Baden's
+Badlands
+Baedeker
+Baedeker's
+Baez
+Baez's
+Baffin
+Baffin's
+Baggies
+Baghdad
+Baghdad's
+Baguio
+Baguio's
+Baha'i
+Baha'ullah
+Bahama
+Bahama's
+Bahamas
+Bahamian
+Bahamian's
+Bahamians
+Bahia
+Bahia's
+Bahrain
+Bahrain's
+Baikal
+Baikal's
+Bailey
+Bailey's
+Baird
+Baird's
+Bakelite
+Bakelite's
+Baker
+Baker's
+Bakersfield
+Bakersfield's
+Baku
+Baku's
+Bakunin
+Bakunin's
+Balanchine
+Balanchine's
+Balaton
+Balaton's
+Balboa
+Balboa's
+Balder
+Balder's
+Baldwin
+Baldwin's
+Balearic
+Balearic's
+Balfour
+Balfour's
+Bali
+Bali's
+Balinese
+Balkan
+Balkans
+Balkhash
+Balkhash's
+Ball
+Ball's
+Ballard
+Ballard's
+Balthazar
+Balthazar's
+Baltic
+Baltimore
+Baltimore's
+Baluchistan
+Baluchistan's
+Balzac
+Balzac's
+Bamako
+Bamako's
+Bambi
+Bambi's
+Banach
+Banach's
+Bancroft
+Bancroft's
+Bandung
+Bandung's
+Bangalore
+Bangalore's
+Bangkok
+Bangkok's
+Bangladesh
+Bangladesh's
+Bangladeshi
+Bangladeshis
+Bangor
+Bangor's
+Bangui
+Bangui's
+Banjarmasin
+Banjarmasin's
+Banjul
+Banjul's
+Banks
+Banneker
+Banneker's
+Bannister
+Bannister's
+Banting
+Banting's
+Bantu
+Bantu's
+Bantus
+Baotou
+Baotou's
+Baptist
+Baptist's
+Baptiste
+Baptiste's
+Baptists
+Barabbas
+Barabbas's
+Barbadian
+Barbadians
+Barbados
+Barbados's
+Barbara
+Barbara's
+Barbarella
+Barbarella's
+Barbarossa
+Barbarossa's
+Barbary
+Barbary's
+Barber
+Barber's
+Barbie
+Barbie's
+Barbour
+Barbour's
+Barbra
+Barbra's
+Barbuda
+Barbuda's
+Barcelona
+Barcelona's
+Barclay
+Barclay's
+Bardeen
+Bardeen's
+Barents
+Barents's
+Barker
+Barker's
+Barkley
+Barkley's
+Barlow
+Barlow's
+Barnabas
+Barnaby
+Barnaby's
+Barnard
+Barnard's
+Barnaul
+Barnaul's
+Barnes
+Barnett
+Barnett's
+Barney
+Barney's
+Barnum
+Barnum's
+Baroda
+Baroda's
+Barquisimeto
+Barquisimeto's
+Barr
+Barr's
+Barranquilla
+Barranquilla's
+Barrera
+Barrera's
+Barrett
+Barrett's
+Barrie
+Barrie's
+Barron
+Barron's
+Barry
+Barry's
+Barrymore
+Barrymore's
+Bart
+Bart's
+Barth
+Barth's
+Bartholdi
+Bartholdi's
+Bartholomew
+Bartholomew's
+Bartlett
+Bartlett's
+Barton
+Barton's
+Bart�k
+Bart�k's
+Baruch
+Baruch's
+Baryshnikov
+Basel
+Basel's
+Basho
+Basho's
+Basie
+Basie's
+Basil
+Basil's
+Basque
+Basque's
+Basques
+Basra
+Basra's
+Bass
+Bass's
+Basseterre
+Basseterre's
+Bastille
+Bastille's
+Bataan
+Bataan's
+Bates
+Bathsheba
+Bathsheba's
+Batista
+Batista's
+Batman
+Batman's
+Battle
+Battle's
+Batu
+Batu's
+Baudelaire
+Baudelaire's
+Baudouin
+Baudouin's
+Bauer
+Bauer's
+Bauhaus
+Bauhaus's
+Baum
+Baum's
+Bavaria
+Bavaria's
+Bavarian
+Bavarians
+Baxter
+Baxter's
+Bayer
+Bayer's
+Bayes
+Bayesian
+Bayeux
+Bayeux's
+Baylor
+Baylor's
+Bayonne
+Bayonne's
+Bayreuth
+Bayreuth's
+Baywatch
+Baywatch's
+Be
+Be's
+Beach
+Beach's
+Beadle
+Beadle's
+Bean
+Bean's
+Beard
+Beard's
+Beardmore
+Beardmore's
+Beardsley
+Beardsley's
+Bearnaise
+Bearnaise's
+Beasley
+Beasley's
+Beatlemania
+Beatlemania's
+Beatles
+Beatles's
+Beatrice
+Beatrice's
+Beatrix
+Beatrix's
+Beatriz
+Beatriz's
+Beau
+Beau's
+Beaufort
+Beaufort's
+Beaujolais
+Beaujolais's
+Beaumarchais
+Beaumarchais's
+Beaumont
+Beaumont's
+Beauregard
+Beauregard's
+Beauvoir
+Beauvoir's
+Bechtel
+Bechtel's
+Beck
+Beck's
+Becker
+Becker's
+Becket
+Becket's
+Beckett
+Beckett's
+Becky
+Becky's
+Becquerel
+Becquerel's
+Bede
+Bede's
+Bedouin
+Bedouin's
+Bedouins
+Beebe
+Beebe's
+Beecher
+Beecher's
+Beefaroni
+Beefaroni's
+Beelzebub
+Beelzebub's
+Beerbohm
+Beerbohm's
+Beethoven
+Beethoven's
+Beeton
+Beeton's
+Begin
+Begin's
+Behan
+Behan's
+Behring
+Behring's
+Beiderbecke
+Beiderbecke's
+Beijing
+Beirut
+Beirut's
+Bekesy
+Bekesy's
+Bela
+Bela's
+Belarus
+Belau
+Belau's
+Belem
+Belem's
+Belfast
+Belfast's
+Belgian
+Belgian's
+Belgians
+Belgium
+Belgium's
+Belgrade
+Belgrade's
+Belinda
+Belinda's
+Belize
+Belize's
+Bell
+Bell's
+Bella
+Bella's
+Bellamy
+Bellamy's
+Bellatrix
+Bellatrix's
+Bellini
+Bellini's
+Bellow
+Bellow's
+Belmont
+Belmont's
+Belmopan
+Belmopan's
+Belshazzar
+Belshazzar's
+Beltane
+Beltane's
+Belushi
+Belushi's
+Ben
+Ben's
+Benacerraf
+Benacerraf's
+Benares's
+Benchley
+Benchley's
+Bender
+Bender's
+Bendix
+Bendix's
+Benedict
+Benedict's
+Benedictine
+Benedictine's
+Benelux
+Benelux's
+Benet
+Benet's
+Benetton
+Benetton's
+Bengal
+Bengal's
+Bengali
+Bengali's
+Benghazi
+Benghazi's
+Benin
+Benin's
+Benita
+Benita's
+Benito
+Benito's
+Benjamin
+Benjamin's
+Bennett
+Bennett's
+Bennie
+Bennie's
+Benny
+Benny's
+Benson
+Benson's
+Bentham
+Bentham's
+Bentley
+Bentley's
+Benton
+Benton's
+Benz
+Benzedrine
+Benzedrine's
+Beowulf
+Beowulf's
+Berber
+Berber's
+Berbers
+Berenice
+Berenice's
+Beretta
+Beretta's
+Berg
+Berg's
+Bergen
+Bergen's
+Berger
+Berger's
+Bergerac
+Bergerac's
+Bergman
+Bergman's
+Bergson
+Bergson's
+Beria
+Beria's
+Bering
+Bering's
+Berkeley
+Berkeley's
+Berkshire
+Berkshire's
+Berkshires
+Berle
+Berle's
+Berlin
+Berlin's
+Berliner
+Berliner's
+Berlins
+Berlioz
+Berlioz's
+Berlitz
+Berlitz's
+Bermuda
+Bermuda's
+Bermudas
+Bern
+Bern's
+Bernadette
+Bernadette's
+Bernadine
+Bernadine's
+Bernard
+Bernard's
+Bernardo
+Bernardo's
+Bernays
+Bernays's
+Bernbach
+Bernbach's
+Berne's
+Bernhardt
+Bernhardt's
+Bernice
+Bernice's
+Bernie
+Bernie's
+Bernini
+Bernini's
+Bernoulli
+Bernoulli's
+Bernstein
+Bernstein's
+Berra
+Berra's
+Berry
+Berry's
+Bert
+Bert's
+Berta
+Berta's
+Bertelsmann
+Bertelsmann's
+Bertha
+Bertha's
+Bertie
+Bertie's
+Bertillon
+Bertillon's
+Bertram
+Bertram's
+Bertrand
+Bertrand's
+Beryl
+Beryl's
+Berzelius
+Berzelius's
+Bess
+Bessel
+Bessel's
+Bessemer
+Bessemer's
+Bessie
+Bessie's
+Best
+Best's
+Betelgeuse
+Betelgeuse's
+Beth
+Beth's
+Bethany
+Bethany's
+Bethe
+Bethe's
+Bethesda
+Bethesda's
+Bethlehem
+Bethlehem's
+Bethune
+Betsy
+Betsy's
+Bette
+Bette's
+Bettie
+Bettie's
+Betty
+Betty's
+Bettye
+Bettye's
+Beulah
+Beulah's
+Beverley
+Beverley's
+Beverly
+Beverly's
+Beyer
+Beyer's
+Bhopal
+Bhopal's
+Bhutan
+Bhutan's
+Bhutto
+Bhutto's
+Bi
+Bi's
+Bialystok
+Bialystok's
+Bianca
+Bianca's
+Bib
+Bib's
+Bible
+Bible's
+Bibles
+Bic
+Bic's
+Biddle
+Biddle's
+Bierce
+Bierce's
+Bigfoot
+Biggles
+Biggles's
+Biko
+Biko's
+Bilbao
+Bilbao's
+Bilbo
+Bilbo's
+Bill
+Bill's
+Billie
+Billie's
+Billings
+Billings's
+Billy
+Billy's
+Bimini
+Bimini's
+Bioko
+Bioko's
+Bird
+Bird's
+Birdseye
+Birdseye's
+Birkenstock
+Birmingham
+Birmingham's
+Biro
+Biro's
+Biscay
+Biscay's
+Biscayne
+Biscayne's
+Bishkek
+Bishop
+Bishop's
+Bismarck
+Bismarck's
+Bismark
+Bismark's
+Bisquick
+Bisquick's
+Bissau
+Bissau's
+Bizet
+Bizet's
+Bk
+Bk's
+Black's
+Blackbeard
+Blackbeard's
+Blackburn
+Blackburn's
+Blackfoot
+Blackfoot's
+Blackshirt
+Blackshirt's
+Blackstone
+Blackstone's
+Blackwell
+Blackwell's
+Blaine
+Blaine's
+Blair
+Blair's
+Blake
+Blake's
+Blanca
+Blanca's
+Blanchard
+Blanchard's
+Blanche
+Blanche's
+Blankenship
+Blankenship's
+Blantyre
+Blantyre's
+Blatz
+Blatz's
+Blavatsky
+Blavatsky's
+Blenheim
+Blenheim's
+Blevins
+Blevins's
+Bligh
+Bligh's
+Bloch
+Bloch's
+Blockbuster
+Blockbuster's
+Bloemfontein
+Bloemfontein's
+Blondel
+Blondel's
+Blondie
+Blondie's
+Bloom
+Bloom's
+Bloomer
+Bloomer's
+Bloomfield
+Bloomfield's
+Bloomingdale
+Bloomingdale's
+Bloomsbury
+Bloomsbury's
+Blucher
+Blucher's
+Bluebeard
+Bluebeard's
+Blvd
+Blythe
+Blythe's
+Boas
+Boas's
+Bob
+Bob's
+Bobbi
+Bobbi's
+Bobbie
+Bobbie's
+Bobbitt
+Bobbitt's
+Bobby
+Bobby's
+Boccaccio
+Boccaccio's
+Bodhidharma
+Bodhidharma's
+Bodhisattva
+Bodhisattva's
+Boeing
+Boeing's
+Boeotia
+Boeotia's
+Boeotian
+Boer
+Boer's
+Boers
+Boethius
+Boethius's
+Bogart
+Bogart's
+Bogot�
+Bogot�'s
+Bohemia
+Bohemia's
+Bohemian
+Bohemian's
+Bohemians
+Bohr
+Bohr's
+Boise
+Boise's
+Bojangles
+Bojangles's
+Boleyn
+Boleyn's
+Bolivar
+Bolivar's
+Bolivia
+Bolivia's
+Bolivian
+Bolivians
+Bologna
+Bologna's
+Bolshevik
+Bolshevik's
+Bolsheviks
+Bolshevism
+Bolshevism's
+Bolshevisms
+Bolshevist
+Bolshevist's
+Bolshevists
+Bolshoi
+Bolshoi's
+Bolton
+Bolton's
+Boltzmann
+Boltzmann's
+Bombay
+Bombay's
+Bonaparte
+Bonaparte's
+Bonaventure
+Bonaventure's
+Bond
+Bond's
+Bonhoeffer
+Bonhoeffer's
+Boniface
+Boniface's
+Bonita
+Bonita's
+Bonn
+Bonn's
+Bonner
+Bonner's
+Bonneville
+Bonneville's
+Bonnie
+Bonnie's
+Booker
+Booker's
+Boole
+Boole's
+Boolean
+Boone
+Boone's
+Booth
+Booth's
+Bordeaux
+Bordeaux's
+Borden
+Borden's
+Bordon
+Bordon's
+Boreas
+Boreas's
+Borg
+Borg's
+Borges
+Borgia
+Borgia's
+Borglum
+Borglum's
+Borgs
+Boris
+Bork
+Bork's
+Borlaug
+Borlaug's
+Born
+Born's
+Borneo
+Borneo's
+Borobudur
+Borobudur's
+Borodin
+Borodin's
+Boru
+Boru's
+Bosch
+Bosch's
+Bose
+Bose's
+Bosnia
+Bosnia's
+Bosporus
+Bosporus's
+Boston
+Boston's
+Bostonian
+Bostonians
+Bostons
+Boswell
+Boswell's
+Botswana
+Botswana's
+Botticelli
+Botticelli's
+Boulder
+Boulder's
+Boulez
+Boulez's
+Bourbaki
+Bourbaki's
+Bourbon
+Bourbon's
+Bournemouth
+Bournemouth's
+Bovary
+Bovary's
+Bowditch
+Bowditch's
+Bowell
+Bowell's
+Bowen
+Bowen's
+Bowers
+Bowery
+Bowery's
+Bowie
+Bowie's
+Bowman
+Bowman's
+Boyd
+Boyd's
+Boyer
+Boyer's
+Boyle
+Boyle's
+Bo�tes
+Br
+Br's
+Brad
+Brad's
+Bradbury
+Bradbury's
+Braddock
+Braddock's
+Bradford
+Bradford's
+Bradley
+Bradley's
+Bradly
+Bradly's
+Bradshaw
+Bradshaw's
+Bradstreet
+Bradstreet's
+Brady
+Brady's
+Bragg
+Bragg's
+Brahe
+Brahe's
+Brahma
+Brahma's
+Brahmagupta
+Brahmagupta's
+Brahman
+Brahman's
+Brahmanism
+Brahmanism's
+Brahmanisms
+Brahmans
+Brahmaputra
+Brahmaputra's
+Brahmas
+Brahmin's
+Brahms
+Braille
+Braille's
+Brailled
+Brailles
+Brailling
+Brain
+Brain's
+Brampton
+Brampton's
+Bran
+Bran's
+Branch
+Branch's
+Brandeis
+Brandeis's
+Branden
+Branden's
+Brandenburg
+Brandenburg's
+Brandi
+Brandi's
+Brandie
+Brandie's
+Brando
+Brando's
+Brandon
+Brandon's
+Brandt
+Brandt's
+Brandy
+Brandy's
+Brant
+Brant's
+Braque
+Braque's
+Brasilia
+Bratislava
+Bratislava's
+Brattain
+Brattain's
+Bray
+Bray's
+Brazil
+Brazil's
+Brazilian
+Brazilians
+Brazos
+Brazos's
+Brazzaville
+Brazzaville's
+Brecht
+Brecht's
+Breckenridge
+Breckenridge's
+Bremen
+Bremen's
+Brenda
+Brenda's
+Brendan
+Brendan's
+Brennan
+Brennan's
+Brenner
+Brenner's
+Brent
+Brent's
+Brenton
+Brenton's
+Brest
+Brest's
+Bret
+Bret's
+Breton
+Brett
+Brett's
+Brewer
+Brewer's
+Brewster
+Brewster's
+Brezhnev
+Brezhnev's
+Brian
+Brian's
+Briana
+Briana's
+Brianna
+Brianna's
+Brice
+Brice's
+Bridalveil
+Bridalveil's
+Bridgeport
+Bridgeport's
+Bridger
+Bridger's
+Bridges
+Bridget
+Bridget's
+Bridgetown
+Bridgetown's
+Bridgett
+Bridgett's
+Bridgette
+Bridgette's
+Bridgman
+Bridgman's
+Brie
+Brie's
+Brigadoon
+Briggs
+Brigham
+Brigham's
+Bright
+Bright's
+Brighton
+Brighton's
+Brigid
+Brigid's
+Brigitte
+Brigitte's
+Brillo
+Brinkley
+Brinkley's
+Brisbane
+Brisbane's
+Bristol
+Bristol's
+Brit
+Brit's
+Britain
+Britain's
+Britannia
+Britannia's
+Britannic
+Britannica
+Britannica's
+British
+Britisher
+Britney
+Britney's
+Briton
+Briton's
+Britons
+Brits
+Britt
+Britt's
+Brittany
+Brittany's
+Britten
+Britten's
+Brittney
+Brittney's
+Brno
+Brno's
+Broadway
+Broadway's
+Broadways
+Brobdingnag
+Brobdingnag's
+Brobdingnagian
+Brock
+Brock's
+Brokaw
+Brokaw's
+Bronson
+Bronson's
+Bronte
+Bronx
+Bronx's
+Brooke
+Brooke's
+Brooklyn
+Brooklyn's
+Brooks
+Brown
+Brown's
+Browne
+Browne's
+Brownian
+Brownian's
+Brownie
+Brownie's
+Brownies
+Browning
+Browning's
+Brownshirt
+Brownsville
+Brownsville's
+Brubeck
+Brubeck's
+Bruce
+Bruce's
+Bruckner
+Bruckner's
+Brueghel's
+Brummel
+Brummel's
+Brunei
+Brunei's
+Brunelleschi
+Brunelleschi's
+Brunhilde
+Brunhilde's
+Bruno
+Bruno's
+Brunswick
+Brunswick's
+Brussels
+Brut
+Brut's
+Brutus
+Brutus's
+Bryan
+Bryan's
+Bryant
+Bryant's
+Bryce
+Bryce's
+Brynner
+Brynner's
+Bryon
+Bryon's
+Brzezinski
+Brzezinski's
+Btu
+Buber
+Buber's
+Buchanan
+Buchanan's
+Bucharest
+Bucharest's
+Buchenwald
+Buchenwald's
+Buchwald
+Buchwald's
+Buck
+Buck's
+Buckingham
+Buckingham's
+Buckley
+Buckley's
+Buckner
+Buckner's
+Bud
+Bud's
+Budapest
+Budapest's
+Buddha
+Buddha's
+Buddhas
+Buddhism
+Buddhism's
+Buddhisms
+Buddhist
+Buddhist's
+Buddhists
+Buddy
+Buddy's
+Budweiser
+Budweiser's
+Buffalo
+Buffalo's
+Buffy
+Buffy's
+Buford
+Buford's
+Bugatti
+Bugatti's
+Buick
+Buick's
+Bujumbura
+Bujumbura's
+Bukhara
+Bukhara's
+Bukharin
+Bukharin's
+Bulawayo
+Bulawayo's
+Bulfinch
+Bulfinch's
+Bulganin
+Bulganin's
+Bulgar
+Bulgar's
+Bulgaria
+Bulgaria's
+Bulgarian
+Bulgarians
+Bullock
+Bullock's
+Bullwinkle
+Bullwinkle's
+Bultmann
+Bultmann's
+Bumppo
+Bumppo's
+Bunche
+Bunche's
+Bundestag
+Bundestag's
+Bunin
+Bunin's
+Bunker
+Bunker's
+Bunsen
+Bunsen's
+Bunyan
+Bunyan's
+Burbank
+Burbank's
+Burch
+Burch's
+Burger
+Burger's
+Burgess
+Burgess's
+Burgoyne
+Burgoyne's
+Burgundian
+Burgundies
+Burgundy
+Burgundy's
+Burke
+Burke's
+Burks
+Burl
+Burl's
+Burma
+Burma's
+Burmese
+Burnett
+Burnett's
+Burns
+Burnside
+Burnside's
+Burr
+Burr's
+Burris
+Burris's
+Burroughs
+Burroughs's
+Bursa
+Bursa's
+Burt
+Burt's
+Burton
+Burton's
+Burundi
+Burundi's
+Busch
+Busch's
+Bush
+Bush's
+Bushido
+Bushido's
+Bushnell
+Bushnell's
+Butler
+Butler's
+Butterfingers
+Butterfingers's
+Buxtehude
+Buxtehude's
+Bu�uel
+Bu�uel's
+Byblos
+Byblos's
+Byelorussia's
+Byers
+Byers's
+Byrd
+Byrd's
+Byron
+Byron's
+Byronic
+Byzantine
+Byzantines
+Byzantium
+Byzantium's
+C
+C's
+CD
+CEO
+CIA
+CO
+COBOL
+COBOLs
+COLA
+CPA
+Ca
+Ca's
+Cabernet
+Cabernet's
+Cabot
+Cabot's
+Cabral
+Cabral's
+Cabrera
+Cabrera's
+Cabrini
+Cabrini's
+Cadillac
+Cadillac's
+Cadiz
+Cadiz's
+Caedmon
+Caedmon's
+Caerphilly
+Caerphilly's
+Caesar
+Caesar's
+Caesars
+Cage
+Cage's
+Cagney
+Cagney's
+Cahokia
+Cahokia's
+Caiaphas
+Caiaphas's
+Cain
+Cain's
+Cains
+Cairo
+Cairo's
+Caitlin
+Caitlin's
+Cajun
+Cajun's
+Cajuns
+Cal
+Cal's
+Calais
+Calais's
+Calcutta
+Calcutta's
+Calder
+Calder's
+Calderon
+Calderon's
+Caldwell
+Caldwell's
+Caleb
+Caleb's
+Caledonia
+Caledonia's
+Calgary
+Calgary's
+Calhoun
+Calhoun's
+Cali
+Cali's
+Caliban
+Caliban's
+California
+California's
+Californian
+Californians
+Caligula
+Caligula's
+Callaghan
+Callaghan's
+Callahan
+Callahan's
+Callao
+Callao's
+Callas
+Callie
+Callie's
+Calliope
+Calliope's
+Callisto
+Callisto's
+Caloocan
+Caloocan's
+Calvary
+Calvary's
+Calvert
+Calvert's
+Calvin
+Calvin's
+Calvinism
+Calvinism's
+Calvinisms
+Calvinist
+Calvinist's
+Calvinistic
+Calvinists
+Camacho
+Camacho's
+Cambodia
+Cambodia's
+Cambodian
+Cambodians
+Cambrian
+Cambridge
+Cambridge's
+Camel
+Camel's
+Camelopardalis
+Camelopardalis's
+Camelot
+Camelot's
+Camembert
+Camembert's
+Camemberts
+Cameron
+Cameron's
+Cameroon
+Cameroon's
+Cameroons
+Camilla
+Camilla's
+Camille
+Camille's
+Camoens
+Camoens's
+Campbell
+Campbell's
+Campinas
+Campinas's
+Campos
+Camry
+Camry's
+Camus
+Camus's
+Canaan
+Canaan's
+Canada
+Canada's
+Canadian
+Canadians
+Canaletto
+Canaletto's
+Canaries
+Canaveral
+Canaveral's
+Canberra
+Canberra's
+Cancer
+Cancer's
+Cancers
+Cancun
+Cancun's
+Candace
+Candace's
+Candice
+Candice's
+Candide
+Candide's
+Candy
+Candy's
+Cannes
+Cannon
+Cannon's
+Canon
+Canon's
+Canopus
+Canopus's
+Cantabrigian
+Canterbury
+Canterbury's
+Canton
+Canton's
+Cantonese
+Cantonese's
+Cantor
+Cantor's
+Cantrell
+Cantrell's
+Cantu
+Cantu's
+Canute
+Canute's
+Capek
+Capek's
+Capella
+Capella's
+Capet
+Capet's
+Capetian
+Capetian's
+Capetown
+Capetown's
+Caph
+Caph's
+Capistrano
+Capistrano's
+Capitol
+Capitol's
+Capitoline
+Capitoline's
+Capitols
+Capone
+Capone's
+Capote
+Capote's
+Capra
+Capri
+Capri's
+Capricorn
+Capricorn's
+Capricorns
+Capt
+Capt's
+Capulet
+Capulet's
+Cara
+Cara's
+Caracalla
+Caracalla's
+Caracas
+Caracas's
+Caravaggio
+Caravaggio's
+Carboloy
+Carboloy's
+Carboniferous
+Carborundum
+Carborundum's
+Cardenas
+Cardenas's
+Cardiff
+Cardiff's
+Cardin
+Cardin's
+Cardozo
+Cardozo's
+Carey
+Carey's
+Carib
+Carib's
+Caribbean
+Caribbeans
+Carina
+Carina's
+Carissa
+Carissa's
+Carl
+Carl's
+Carla
+Carla's
+Carlene
+Carlene's
+Carlin
+Carlin's
+Carlo
+Carlo's
+Carlos
+Carlsbad
+Carlsbad's
+Carlson
+Carlson's
+Carlton
+Carlton's
+Carly
+Carly's
+Carlyle
+Carlyle's
+Carmela
+Carmela's
+Carmella
+Carmella's
+Carmelo
+Carmelo's
+Carmen
+Carmen's
+Carmichael
+Carmichael's
+Carmine
+Carmine's
+Carnap
+Carnap's
+Carnation
+Carnation's
+Carnegie
+Carnegie's
+Carney
+Carney's
+Carnot
+Carnot's
+Carol
+Carol's
+Carole
+Carole's
+Carolina
+Carolina's
+Caroline
+Carolingian
+Carolinian
+Carolyn
+Carolyn's
+Carpathian
+Carpathian's
+Carpathians
+Carpenter
+Carpenter's
+Carr
+Carr's
+Carranza
+Carranza's
+Carrie
+Carrie's
+Carrier
+Carrier's
+Carrillo
+Carrillo's
+Carroll
+Carroll's
+Carson
+Carson's
+Carter
+Carter's
+Cartesian
+Carthage
+Carthage's
+Carthaginian
+Cartier
+Cartier's
+Cartwright
+Cartwright's
+Caruso
+Caruso's
+Carver
+Carver's
+Cary
+Cary's
+Casablanca
+Casablanca's
+Casals
+Casals's
+Casandra
+Casandra's
+Casanova
+Casanova's
+Casanovas
+Cascades
+Cascades's
+Case
+Case's
+Casey
+Casey's
+Cash
+Cash's
+Casio
+Casio's
+Caspar
+Caspar's
+Caspian
+Cassandra
+Cassandra's
+Cassatt
+Cassatt's
+Cassie
+Cassie's
+Cassiopeia
+Cassiopeia's
+Cassius
+Cassius's
+Castaneda
+Castaneda's
+Castillo
+Castillo's
+Castlereagh
+Castlereagh's
+Castor
+Castor's
+Castries
+Castries's
+Castro
+Castro's
+Catalan
+Catalan's
+Catalina
+Catalina's
+Catalonia
+Catalonia's
+Catawba
+Catawba's
+Caterpillar
+Cathay
+Cathay's
+Cather
+Cather's
+Catherine
+Catherine's
+Cathleen
+Cathleen's
+Catholic
+Catholicism
+Catholicism's
+Catholicisms
+Catholics
+Cathryn
+Cathryn's
+Cathy
+Cathy's
+Catiline
+Catiline's
+Cato
+Cato's
+Catskill
+Catskill's
+Catskills
+Catt
+Catt's
+Catullus
+Catullus's
+Caucasian
+Caucasians
+Caucasoid
+Caucasoids
+Caucasus
+Caucasus's
+Cauchy
+Cauchy's
+Cavendish
+Cavendish's
+Cavour
+Cavour's
+Caxton
+Caxton's
+Cayenne
+Cayenne's
+Cayman
+Cayman's
+Cayuga
+Cayuga's
+Cd
+Cd's
+Ceausescu
+Ceausescu's
+Cebu
+Cebu's
+Cebuano
+Cebuano's
+Cecelia
+Cecelia's
+Cecil
+Cecil's
+Cecile
+Cecile's
+Cecilia
+Cecilia's
+Cecily
+Cecily's
+Cedric
+Cedric's
+Celebes's
+Celeste
+Celeste's
+Celia
+Celia's
+Celina
+Celina's
+Cellini
+Cellini's
+Celsius
+Celsiuses
+Celt
+Celt's
+Celtic
+Celtic's
+Celtics
+Celts
+Cenozoic
+Centaurus
+Centaurus's
+Centigrade
+Cepheid
+Cepheus
+Cepheus's
+Cerberus
+Cerberus's
+Cerenkov
+Cerenkov's
+Ceres
+Ceres's
+Cerf
+Cerf's
+Cervantes
+Cervantes's
+Cesar
+Cesar's
+Cesarean
+Cessna
+Cessna's
+Cetus
+Cetus's
+Ceylon
+Ceylon's
+Cezanne
+Cf
+Cf's
+Ch'in
+Chablis
+Chablis's
+Chad
+Chad's
+Chadwick
+Chadwick's
+Chagall
+Chagall's
+Chaitanya
+Chaitanya's
+Chaitin
+Chaitin's
+Chaldean
+Chaldean's
+Challenger
+Challenger's
+Chamberlain
+Chamberlain's
+Chambers
+Chambers's
+Champlain
+Champlain's
+Champollion
+Champollion's
+Chan
+Chan's
+Chance
+Chance's
+Chancellorsville
+Chancellorsville's
+Chandigarh
+Chandigarh's
+Chandler
+Chandler's
+Chandra
+Chandra's
+Chandragupta
+Chandragupta's
+Chandrasekhar
+Chandrasekhar's
+Chanel
+Chanel's
+Chaney
+Chaney's
+Chang
+Chang's
+Changchun
+Changchun's
+Changsha
+Changsha's
+Chantilly
+Chantilly's
+Chanukah's
+Chaplin
+Chaplin's
+Chapman
+Chapman's
+Chappaquiddick
+Chappaquiddick's
+Chapultepec
+Chapultepec's
+Charbray
+Charbray's
+Chardonnay
+Charity
+Charity's
+Charlemagne
+Charlemagne's
+Charlene
+Charlene's
+Charles
+Charles's
+Charleston
+Charleston's
+Charlestons
+Charley
+Charley's
+Charlie
+Charlie's
+Charlotte
+Charlotte's
+Charlottetown
+Charlottetown's
+Charmaine
+Charmaine's
+Charmin
+Charmin's
+Charolais
+Charon
+Charon's
+Chartism
+Chartism's
+Chartres
+Chartres's
+Charybdis
+Charybdis's
+Chase
+Chase's
+Chasity
+Chasity's
+Chateaubriand
+Chattahoochee
+Chattahoochee's
+Chattanooga
+Chattanooga's
+Chatterley
+Chatterley's
+Chatterton
+Chatterton's
+Chaucer
+Chaucer's
+Chauncey
+Chauncey's
+Chautauqua
+Chautauqua's
+Chavez
+Chavez's
+Chayefsky
+Chayefsky's
+Che
+Che's
+Chechen
+Chechen's
+Chechnya
+Chechnya's
+Cheddar
+Cheddar's
+Cheddars
+Cheer
+Cheer's
+Cheerios
+Cheerios's
+Cheetos
+Cheetos's
+Cheever
+Chekhov
+Chekhov's
+Chelsea
+Chelsea's
+Chelyabinsk
+Chelyabinsk's
+Chen
+Chen's
+Cheney
+Cheney's
+Chengdu
+Chennai
+Chennai's
+Cheops
+Cheops's
+Cheri
+Cheri's
+Cherie
+Cherie's
+Chernenko
+Chernenko's
+Chernobyl
+Chernobyl's
+Chernomyrdin
+Chernomyrdin's
+Cherokee
+Cherokee's
+Cherokees
+Cherry
+Cherry's
+Cheryl
+Cheryl's
+Chesapeake
+Chesapeake's
+Cheshire
+Cheshire's
+Chester
+Chester's
+Chesterfield
+Chesterfield's
+Chesterton
+Chesterton's
+Chevalier
+Chevalier's
+Cheviot
+Cheviot's
+Chevrolet
+Chevrolet's
+Chevron
+Chevron's
+Chevy
+Chevy's
+Cheyenne
+Cheyenne's
+Cheyennes
+Chi
+Chi's
+Chianti
+Chiantis
+Chiba
+Chiba's
+Chibcha
+Chibcha's
+Chicago
+Chicago's
+Chicagoan
+Chicagoan's
+Chicana
+Chicanas
+Chicano
+Chicano's
+Chicanos
+Chickasaw
+Chickasaw's
+Chiclets
+Chiclets's
+Chihuahua
+Chihuahua's
+Chihuahuas
+Chile
+Chile's
+Chilean
+Chileans
+Chimborazo
+Chimborazo's
+Chimera
+Chimu
+Chimu's
+China
+China's
+Chinatown
+Chinatown's
+Chinatowns
+Chinese
+Chinook
+Chinook's
+Chinooks
+Chipewyan
+Chipewyan's
+Chippendale
+Chippendale's
+Chippewa
+Chippewa's
+Chiquita
+Chiquita's
+Chirico
+Chirico's
+Chisholm
+Chisholm's
+Chisinau
+Chittagong
+Chittagong's
+Chivas
+Chivas's
+Chloe
+Chloe's
+Choctaw
+Choctaw's
+Chomsky
+Chomsky's
+Chongqing
+Chopin
+Chopin's
+Chopra
+Chopra's
+Chou
+Chou's
+Chretien
+Chretien's
+Chris
+Chris's
+Christ
+Christ's
+Christa
+Christa's
+Christchurch
+Christchurch's
+Christendom
+Christendom's
+Christendoms
+Christensen
+Christensen's
+Christi
+Christi's
+Christian
+Christian's
+Christianities
+Christianity
+Christianity's
+Christians
+Christie
+Christie's
+Christies
+Christina
+Christina's
+Christine
+Christine's
+Christmas
+Christmas's
+Christmases
+Christoper
+Christoper's
+Christopher
+Christopher's
+Christs
+Christy's
+Chrysler
+Chrysler's
+Chrysostom
+Chrysostom's
+Chrystal
+Chrystal's
+Chuck
+Chuck's
+Chukchi
+Chukchi's
+Chumash
+Chumash's
+Chung
+Chung's
+Chungking's
+Church
+Church's
+Churchill
+Churchill's
+Churriguera
+Churriguera's
+Chuvash
+Chuvash's
+Ci
+Cicero
+Cicero's
+Cid
+Cid's
+Cimabue
+Cimabue's
+Cincinnati
+Cincinnati's
+Cinderella
+Cinderella's
+Cinderellas
+Cindy
+Cindy's
+CinemaScope
+CinemaScope's
+Cinerama
+Cinerama's
+Cipro
+Circe
+Circe's
+Citibank
+Citibank's
+Citroen
+Citroen's
+Cl
+Cl's
+Claiborne
+Claiborne's
+Clair
+Clair's
+Claire
+Claire's
+Clairol
+Clairol's
+Clancy
+Clancy's
+Clapeyron
+Clapeyron's
+Clapton
+Clapton's
+Clara
+Clara's
+Clare
+Clare's
+Clarence
+Clarence's
+Clarendon
+Clarendon's
+Clarice
+Clarice's
+Clarissa
+Clarissa's
+Clark
+Clark's
+Clarke
+Clarke's
+Claude
+Claude's
+Claudette
+Claudette's
+Claudia
+Claudia's
+Claudine
+Claudine's
+Claudio
+Claudio's
+Claudius
+Claudius's
+Claus
+Claus's
+Clausewitz
+Clausewitz's
+Clausius
+Clausius's
+Clay
+Clay's
+Clayton
+Clayton's
+Clearasil
+Clearasil's
+Clem
+Clem's
+Clemenceau
+Clemenceau's
+Clemens
+Clement
+Clement's
+Clementine
+Clementine's
+Clements
+Clemons
+Clemson
+Clemson's
+Cleo
+Cleo's
+Cleopatra
+Cleopatra's
+Cleveland
+Cleveland's
+Cliburn
+Cliburn's
+Cliff
+Cliff's
+Clifford
+Clifford's
+Clifton
+Clifton's
+Cline
+Cline's
+Clint
+Clint's
+Clinton
+Clinton's
+Clio
+Clio's
+Clive
+Clive's
+Clorets
+Clorets's
+Clorox
+Clorox's
+Clotho
+Clotho's
+Clouseau
+Clouseau's
+Clovis
+Clovis's
+Clyde
+Clyde's
+Clydesdale
+Clydesdale's
+Clytemnestra
+Clytemnestra's
+Cm
+Cm's
+Co
+Co's
+Cobain
+Cobain's
+Cobb
+Cobb's
+Cochabamba
+Cochabamba's
+Cochin
+Cochin's
+Cochise
+Cochise's
+Cochran
+Cochran's
+Cockney
+Cocteau
+Cocteau's
+Cody
+Cody's
+Coffey
+Coffey's
+Cognac
+Cognac's
+Cohan
+Cohan's
+Cohen
+Cohen's
+Coimbatore
+Coimbatore's
+Cointreau
+Cointreau's
+Coke
+Coke's
+Cokes
+Col
+Col's
+Colbert
+Colbert's
+Colby
+Colby's
+Cole
+Cole's
+Coleen
+Coleen's
+Coleman
+Coleman's
+Coleridge
+Coleridge's
+Colette
+Colette's
+Colfax
+Colfax's
+Colgate
+Colgate's
+Colin
+Colin's
+Colleen
+Colleen's
+Collier
+Collier's
+Collin
+Collin's
+Collins
+Colo
+Colo's
+Cologne
+Cologne's
+Colombia
+Colombia's
+Colombian
+Colombians
+Colombo
+Colombo's
+Colon
+Colon's
+Colorado
+Colorado's
+Colosseum
+Colosseum's
+Colt
+Colt's
+Coltrane
+Coltrane's
+Columbia
+Columbia's
+Columbine
+Columbine's
+Columbus
+Columbus's
+Com
+Com's
+Comanche
+Comanche's
+Comanches
+Combs
+Combs's
+Comintern
+Comintern's
+Commons
+Commons's
+Commonwealth
+Commonwealth's
+Commonwealths
+Communion
+Communion's
+Communions
+Communism
+Communisms
+Communist
+Communists
+Como
+Como's
+Comoros
+Compaq
+Compaq's
+Compton
+Compton's
+CompuServe
+CompuServe's
+Comte
+Comte's
+Conakry
+Conakry's
+Conan
+Conan's
+Concepci�n
+Concepci�n's
+Concetta
+Concetta's
+Concord
+Concord's
+Concorde
+Concorde's
+Concords
+Condillac
+Condillac's
+Condorcet
+Condorcet's
+Conestoga
+Confederacy
+Confederacy's
+Confederate
+Confederates
+Confucian
+Confucianism
+Confucianism's
+Confucianisms
+Confucians
+Confucius
+Confucius's
+Cong
+Cong's
+Congo
+Congo's
+Congolese
+Congregationalist
+Congregationalists
+Congress
+Congress's
+Congresses
+Congreve
+Congreve's
+Conley
+Conley's
+Conn
+Conn's
+Connecticut
+Connecticut's
+Connemara
+Connemara's
+Conner
+Conner's
+Connery
+Connery's
+Connie
+Connie's
+Connolly
+Connolly's
+Connors
+Conrad
+Conrad's
+Conrail
+Conrail's
+Constable
+Constable's
+Constance
+Constance's
+Constantine
+Constantine's
+Constantinople
+Constantinople's
+Constitution
+Consuelo
+Consuelo's
+Continent
+Continent's
+Continental
+Contreras
+Contreras's
+Conway
+Conway's
+Cook
+Cook's
+Cooke
+Cooke's
+Cooley
+Cooley's
+Coolidge
+Coolidge's
+Cooper
+Cooper's
+Cooperstown
+Cooperstown's
+Coors
+Coors's
+Copacabana
+Copacabana's
+Copeland
+Copeland's
+Copenhagen
+Copenhagen's
+Copernican
+Copernicus
+Copernicus's
+Copland
+Copland's
+Copley
+Copley's
+Copperfield
+Copperfield's
+Coppertone
+Coppertone's
+Coppola
+Coppola's
+Coptic
+Coptic's
+Cora
+Cora's
+Cordelia
+Cordelia's
+Cordilleras
+Cordoba
+Corey
+Corey's
+Corfu
+Corfu's
+Corina
+Corina's
+Corine
+Corine's
+Corinne
+Corinne's
+Corinth
+Corinth's
+Corinthian
+Corinthians
+Corinthians's
+Coriolanus
+Coriolanus's
+Coriolis
+Coriolis's
+Corleone
+Corleone's
+Cormack
+Cormack's
+Corneille
+Corneille's
+Cornelia
+Cornelia's
+Cornelius
+Cornelius's
+Cornell
+Cornell's
+Corning
+Corning's
+Cornish
+Cornwall
+Cornwall's
+Cornwallis
+Cornwallis's
+Coronado
+Coronado's
+Corot
+Corot's
+Correggio
+Correggio's
+Corrine
+Corrine's
+Corsica
+Corsica's
+Corsican
+Cortes
+Corteses
+Cortez's
+Cortland
+Cortland's
+Corvallis
+Corvallis's
+Corvette
+Corvette's
+Corvus
+Corvus's
+Cory
+Cory's
+Cosby
+Cosby's
+Cossack
+Cossack's
+Cossacks
+Costco
+Costco's
+Costello
+Costello's
+Costner
+Costner's
+Cote
+Cote's
+Cotonou
+Cotonou's
+Cotopaxi
+Cotopaxi's
+Cotswold
+Cotswold's
+Cotton
+Cotton's
+Coulomb
+Coulomb's
+Couperin
+Couperin's
+Courbet
+Courbet's
+Courtney
+Courtney's
+Cousteau
+Cousteau's
+Coventries
+Coventry
+Coventry's
+Coward
+Coward's
+Cowley
+Cowley's
+Cowper
+Cowper's
+Cox
+Cox's
+Coy
+Coy's
+Cozumel
+Cozumel's
+Cr
+Cr's
+Crabbe
+Crabbe's
+Craft
+Craft's
+Craig
+Craig's
+Cranach
+Cranach's
+Crane
+Crane's
+Cranmer
+Cranmer's
+Crater
+Crater's
+Crawford
+Crawford's
+Cray
+Cray's
+Crayola
+Crayola's
+Creation
+Creation's
+Creator
+Creator's
+Crecy
+Crecy's
+Cree
+Cree's
+Creek
+Creek's
+Creighton
+Creighton's
+Creole
+Creole's
+Creoles
+Creon
+Creon's
+Crest
+Crest's
+Cretaceous
+Cretan
+Crete
+Crete's
+Crichton
+Crichton's
+Crick
+Crick's
+Crimea
+Crimea's
+Crimean
+Criollo
+Crisco
+Crisco's
+Cristina
+Cristina's
+Croat
+Croat's
+Croatia
+Croatia's
+Croatian
+Croatians
+Croats
+Croce
+Croce's
+Crockett
+Crockett's
+Croesus
+Croesus's
+Cromwell
+Cromwell's
+Cromwellian
+Cronin
+Cronin's
+Cronkite
+Cronkite's
+Cronus
+Cronus's
+Crookes
+Crookes's
+Crosby
+Crosby's
+Cross
+Cross's
+Crowley
+Crowley's
+Cruikshank
+Cruikshank's
+Cruise
+Cruise's
+Crusoe
+Crusoe's
+Crux
+Crux's
+Cruz
+Cruz's
+Cryptozoic
+Cryptozoic's
+Crystal
+Crystal's
+Cs
+Csonka
+Csonka's
+Ctesiphon
+Ctesiphon's
+Cu
+Cu's
+Cuba
+Cuba's
+Cuban
+Cubans
+Cuchulain
+Cuchulain's
+Cuisinart
+Culbertson
+Culbertson's
+Cullen
+Cullen's
+Cumberland
+Cumberland's
+Cummings
+Cunard
+Cunard's
+Cunningham
+Cunningham's
+Cupid
+Cupid's
+Curacao
+Curacao's
+Curie
+Curie's
+Curitiba
+Curitiba's
+Currier
+Currier's
+Curry
+Curry's
+Curt
+Curt's
+Curtis
+Curtis's
+Custer
+Custer's
+Cuvier
+Cuvier's
+Cuzco
+Cuzco's
+Cybele
+Cybele's
+Cyclades
+Cyclops
+Cyclops's
+Cygnus
+Cygnus's
+Cynthia
+Cynthia's
+Cyprian
+Cypriot
+Cypriot's
+Cypriots
+Cyprus
+Cyprus's
+Cyrano
+Cyrano's
+Cyril
+Cyril's
+Cyrillic
+Cyrus
+Cyrus's
+Czech
+Czechoslovakia
+Czechoslovakia's
+Czechoslovakian
+Czechoslovakians
+Czechs
+Czerny
+Czerny's
+D
+D's
+DC
+DDT
+DDTs
+DEC
+DECed
+DECing
+DECs
+DJ
+DNA
+DP
+DPs
+DVD
+DVDs
+Dacca's
+Dachau
+Dachau's
+Dacron
+Dacron's
+Dacrons
+Dada
+Dada's
+Dadaism
+Dadaism's
+Daedalus
+Daedalus's
+Daguerre
+Daguerre's
+Dagwood
+Dagwood's
+Dahomey
+Dahomey's
+Daimler
+Daimler's
+Daisy
+Daisy's
+Dakar
+Dakar's
+Dakota
+Dakota's
+Dakotan
+Dakotas
+Dale
+Dale's
+Daley
+Daley's
+Dali
+Dali's
+Dalian
+Dalian's
+Dallas
+Dallas's
+Dalmatian
+Dalmatian's
+Dalmatians
+Dalton
+Dalton's
+Damascus
+Damascus's
+Damian
+Damian's
+Damien
+Damien's
+Damion
+Damion's
+Damocles
+Damocles's
+Damon
+Damon's
+Dan
+Dan's
+Dana
+Dana's
+Dane
+Dane's
+Danelaw
+Danelaw's
+Danes
+Dangerfield
+Dangerfield's
+Danial
+Danial's
+Daniel
+Daniel's
+Danielle
+Danielle's
+Daniels
+Danish
+Dannie
+Dannie's
+Danny
+Danny's
+Dante
+Dante's
+Danton
+Danton's
+Danube
+Danube's
+Danubian
+Daphne
+Daphne's
+Darby
+Darby's
+Darcy
+Darcy's
+Dardanelles
+Dare
+Dare's
+Daren
+Daren's
+Darin
+Darin's
+Dario
+Dario's
+Darius
+Darius's
+Darjeeling
+Darjeeling's
+Darla
+Darla's
+Darlene
+Darlene's
+Darling
+Darling's
+Darnell
+Darnell's
+Darrel
+Darrel's
+Darrell
+Darrell's
+Darren
+Darren's
+Darrin
+Darrin's
+Darrow
+Darrow's
+Darryl
+Darryl's
+Darth
+Darth's
+Dartmoor
+Dartmoor's
+Dartmouth
+Dartmouth's
+Darvon
+Darvon's
+Darwin
+Darwin's
+Darwinian
+Darwinism
+Darwinism's
+Daryl
+Daryl's
+Datamation
+Datamations
+Daugherty
+Daugherty's
+Daumier
+Daumier's
+Davao
+Davao's
+Dave
+Dave's
+Davenport
+Davenport's
+David
+David's
+Davids
+Davidson
+Davidson's
+Davies
+Davis
+Davis's
+Davy
+Davy's
+Dawes
+Dawes's
+Dawn
+Dawn's
+Dawson
+Dawson's
+Day
+Day's
+Dayton
+Dayton's
+DeGeneres
+DeGeneres's
+Deadhead
+Deadhead's
+Dean
+Dean's
+Deana
+Deana's
+Deandre
+Deandre's
+Deann
+Deann's
+Deanna
+Deanna's
+Deanne
+Deanne's
+Debbie
+Debbie's
+Debby
+Debby's
+Debora
+Debora's
+Deborah
+Deborah's
+Debouillet
+Debouillet's
+Debra
+Debra's
+Debs
+Debussy
+Debussy's
+Dec
+Dec's
+Decalogue
+Decalogue's
+Decatur
+Decatur's
+Decca
+Decca's
+Deccan
+Deccan's
+December
+December's
+Decembers
+Decker
+Decker's
+Dedekind
+Dedekind's
+Dee
+Dee's
+Deena
+Deena's
+Deere
+Deere's
+Defoe
+Defoe's
+Degas
+Degas's
+Deidre
+Deidre's
+Deimos
+Deimos's
+Deirdre
+Deirdre's
+Deity
+Deity's
+Dejesus
+Dejesus's
+Del
+Del's
+Delacroix
+Delacroix's
+Delacruz
+Delacruz's
+Delaney
+Delaney's
+Delano
+Delano's
+Delaware
+Delaware's
+Delawarean
+Delawarean's
+Delawareans
+Delawares
+Delbert
+Delbert's
+Deleon
+Deleon's
+Delgado
+Delgado's
+Delhi
+Delhi's
+Delia
+Delia's
+Delibes
+Delibes's
+Delicious
+Delilah
+Delilah's
+Delius
+Delius's
+Della
+Della's
+Delmar
+Delmar's
+Delmarva
+Delmarva's
+Delmer
+Delmer's
+Delmonico
+Delores
+Delores's
+Deloris
+Deloris's
+Delphi
+Delphi's
+Delphic
+Delphinus
+Delphinus's
+Delta
+Delta's
+Dem
+Dem's
+Demavend
+Demavend's
+Demerol
+Demerol's
+Demeter
+Demeter's
+Demetrius
+Demetrius's
+Deming
+Deming's
+Democrat
+Democrat's
+Democratic
+Democrats
+Democritus
+Democritus's
+Demosthenes
+Demosthenes's
+Dempsey
+Dempsey's
+Dena
+Dena's
+Deneb
+Deneb's
+Denebola
+Denebola's
+Deng
+Deng's
+Denis
+Denise
+Denise's
+Denmark
+Denmark's
+Dennis
+Denny
+Denny's
+Denver
+Denver's
+Deon
+Deon's
+Derbies
+Derby
+Derby's
+Derek
+Derek's
+Derick
+Derick's
+Derrick
+Derrick's
+Derrida
+Derrida's
+Descartes
+Descartes's
+Desdemona
+Desdemona's
+Desiree
+Desiree's
+Desmond
+Desmond's
+Detroit
+Detroit's
+Deuteronomy
+Deuteronomy's
+Devanagari
+Devanagari's
+Devi
+Devi's
+Devin
+Devin's
+Devon
+Devon's
+Devonian
+Dewar
+Dewar's
+Dewayne
+Dewayne's
+Dewey
+Dewey's
+Dewitt
+Dewitt's
+Dexedrine
+Dexedrine's
+Dexter
+Dexter's
+Dhaka
+Dhaulagiri
+Dhaulagiri's
+Di
+Di's
+DiCaprio
+DiCaprio's
+DiMaggio
+DiMaggio's
+Diaghilev
+Diaghilev's
+Dial
+Dial's
+Diana
+Diana's
+Diane
+Diane's
+Diann
+Diann's
+Dianna
+Dianna's
+Dianne
+Dianne's
+Diaspora
+Diaspora's
+Diaz's
+Dick
+Dick's
+Dickens
+Dickens's
+Dickerson
+Dickerson's
+Dickinson
+Dickinson's
+Dickson
+Dickson's
+Dictaphone
+Dictaphone's
+Diderot
+Diderot's
+Dido
+Dido's
+Didrikson
+Didrikson's
+Diefenbaker
+Diefenbaker's
+Diego
+Diego's
+Diem
+Diem's
+Diesel's
+Dietrich
+Dietrich's
+Dijkstra
+Dijkstra's
+Dijon
+Dijon's
+Dilbert
+Dilbert's
+Dilberts
+Dillard
+Dillard's
+Dillinger
+Dillinger's
+Dillon
+Dillon's
+Dina
+Dina's
+Dinah
+Dinah's
+Dino
+Dino's
+Diocletian
+Diocletian's
+Diogenes
+Diogenes's
+Dion
+Dion's
+Dionne
+Dionne's
+Dionysian
+Dionysus
+Dionysus's
+Diophantine
+Diophantine's
+Dior
+Dior's
+Dipper
+Dipper's
+Dirac
+Dirac's
+Dirichlet
+Dirichlet's
+Dirk
+Dirk's
+Dis
+Disney
+Disney's
+Disneyland
+Disneyland's
+Disraeli
+Disraeli's
+Diwali
+Diwali's
+Dix
+Dix's
+Dixie
+Dixie's
+Dixiecrat
+Dixiecrat's
+Dixieland
+Dixieland's
+Dixielands
+Dixon
+Dixon's
+Djakarta's
+Djibouti
+Djibouti's
+Dmitri
+Dmitri's
+Dnepropetrovsk
+Dnepropetrovsk's
+Dnieper's
+Dniester
+Dniester's
+Dobbin
+Dobbin's
+Doberman
+Dobro
+Dobro's
+Doctor
+Doctorow
+Doctorow's
+Dodge
+Dodge's
+Dodgson
+Dodgson's
+Dodoma
+Dodoma's
+Dodson
+Dodson's
+Doe
+Doe's
+Doha
+Doha's
+Dolbies
+Dolby
+Dolby's
+Dole
+Dole's
+Dollie
+Dollie's
+Dolly
+Dolly's
+Dolores
+Dolores's
+Domesday
+Domesday's
+Domingo
+Domingo's
+Dominguez
+Dominguez's
+Dominic
+Dominic's
+Dominica
+Dominica's
+Dominican
+Dominican's
+Dominicans
+Dominick
+Dominick's
+Dominique
+Dominique's
+Domitian
+Domitian's
+Don
+Don's
+Dona
+Dona's
+Donahue
+Donahue's
+Donald
+Donald's
+Donaldson
+Donaldson's
+Donatello
+Donatello's
+Donetsk
+Donetsk's
+Donizetti
+Donizetti's
+Donn
+Donn's
+Donna
+Donna's
+Donne
+Donne's
+Donnell
+Donnell's
+Donner
+Donner's
+Donnie
+Donnie's
+Donny
+Donny's
+Donovan
+Donovan's
+Dooley
+Dooley's
+Doolittle
+Doolittle's
+Doonesbury
+Doonesbury's
+Doppler
+Doppler's
+Dora
+Dora's
+Dorcas
+Doreen
+Doreen's
+Dorian
+Dorian's
+Doric
+Doris
+Doritos
+Doritos's
+Dorothea
+Dorothea's
+Dorothy
+Dorothy's
+Dorset
+Dorset's
+Dorsey
+Dorsey's
+Dorthy
+Dorthy's
+Dortmund
+Dortmund's
+Dostoevsky
+Dostoevsky's
+Dot
+Dot's
+Dotson
+Dotson's
+Douala
+Douala's
+Douay
+Douay's
+Doubleday
+Doubleday's
+Doug
+Doug's
+Douglas
+Douglas's
+Douglass
+Douro
+Douro's
+Dover
+Dover's
+Dow
+Dow's
+Downs
+Downy
+Downy's
+Doyle
+Doyle's
+Dr
+Dr's
+Draco
+Draco's
+Draconian
+Dracula
+Dracula's
+Drake
+Drake's
+Dramamine
+Dramamine's
+Drambuie
+Drambuie's
+Drano
+Drano's
+Dravidian
+Dravidian's
+Dreiser
+Dreiser's
+Dresden
+Dresden's
+Drew
+Drew's
+Dreyfus
+Dreyfus's
+Dristan
+Dristan's
+Druid's
+Dryden
+Dryden's
+Dshubba
+Dshubba's
+DuPont
+DuPont's
+Duane
+Duane's
+Dubai
+Dubai's
+Dubcek
+Dubcek's
+Dubhe
+Dubhe's
+Dublin
+Dublin's
+Dubrovnik
+Dubrovnik's
+Duchamp
+Duchamp's
+Dudley
+Dudley's
+Duffy
+Duffy's
+Duisburg
+Duisburg's
+Duke
+Duke's
+Dulles
+Dulles's
+Duluth
+Duluth's
+Dumas
+Dumbo
+Dumbo's
+Dumpster
+Dumpsters
+Dunant
+Dunant's
+Dunbar
+Dunbar's
+Duncan
+Duncan's
+Dunedin
+Dunedin's
+Dunkirk
+Dunkirk's
+Dunlap
+Dunlap's
+Dunn
+Dunn's
+Dunne
+Dunne's
+Duracell
+Duracell's
+Duran
+Duran's
+Durant
+Durant's
+Durante
+Durante's
+Durban
+Durban's
+Durex
+Durex's
+Durham
+Durham's
+Durhams
+Durkheim
+Durkheim's
+Duroc
+Duroc's
+Durocher
+Durocher's
+Duse
+Duse's
+Dushanbe
+Dushanbe's
+Dustbuster
+Dustbuster's
+Dustin
+Dustin's
+Dusty
+Dusty's
+Dutch
+Dutch's
+Dutchman
+Dutchman's
+Dutchmen
+Duvalier
+Duvalier's
+Dvina
+Dvina's
+Dvor�k
+Dvor�k's
+Dwayne
+Dwayne's
+Dwight
+Dwight's
+Dyer
+Dyer's
+Dylan
+Dylan's
+Dyson
+Dyson's
+Dzerzhinsky
+Dzerzhinsky's
+Dzungaria
+Dzungaria's
+D�rer
+D�rer's
+D�sseldorf
+E
+E's
+EFL
+ER
+ESL
+ESP
+Eakins
+Eakins's
+Earhart
+Earhart's
+Earl
+Earl's
+Earle
+Earle's
+Earlene
+Earlene's
+Earline
+Earline's
+Earnest
+Earnest's
+Earnestine
+Earnestine's
+Earnhardt
+Earnhardt's
+Earp
+Earp's
+East
+East's
+Easter
+Easter's
+Eastern
+Easterner
+Easterner's
+Easterners
+Easters
+Eastman
+Eastman's
+Easts
+Eastwood
+Eastwood's
+Eaton
+Eaton's
+Eben
+Eben's
+Ebeneezer
+Ebeneezer's
+Ebert
+Ebert's
+Ebola
+Ebonics
+Ebony
+Ebony's
+Ebro
+Ebro's
+Ecclesiastes
+Ecclesiastes's
+Eco
+Eco's
+Ecuador
+Ecuador's
+Ecuadoran
+Ecuadorans
+Ecuadorian
+Ecuadorians
+Ed
+Ed's
+Edam
+Edam's
+Edams
+Edda
+Edda's
+Eddie
+Eddie's
+Eddington
+Eddington's
+Eddy
+Eddy's
+Eden
+Eden's
+Edens
+Edgar
+Edgar's
+Edgardo
+Edgardo's
+Edinburgh
+Edinburgh's
+Edison
+Edison's
+Edith
+Edith's
+Edmond
+Edmond's
+Edmonton
+Edmonton's
+Edmund
+Edmund's
+Edna
+Edna's
+Edsel
+Edsel's
+Eduardo
+Eduardo's
+Edward
+Edward's
+Edwardian
+Edwardo
+Edwardo's
+Edwards
+Edwin
+Edwin's
+Edwina
+Edwina's
+Eeyore
+Eeyore's
+Effie
+Effie's
+Efrain
+Efrain's
+Efren
+Efren's
+Eggo
+Eggo's
+Egypt
+Egypt's
+Egyptian
+Egyptians
+Egyptology
+Egyptology's
+Ehrenberg
+Ehrenberg's
+Ehrlich
+Ehrlich's
+Eichmann
+Eichmann's
+Eiffel
+Eiffel's
+Eileen
+Eileen's
+Einstein
+Einstein's
+Einsteins
+Eire
+Eire's
+Eisenhower
+Eisenhower's
+Eisenstein
+Eisenstein's
+Eisner
+Eisner's
+Elaine
+Elaine's
+Elam
+Elam's
+Elanor
+Elanor's
+Elba
+Elba's
+Elbe
+Elbe's
+Elbert
+Elbert's
+Elbrus
+Elbrus's
+Eldon
+Eldon's
+Eleanor
+Eleanor's
+Eleazar
+Eleazar's
+Electra
+Electra's
+Elena
+Elena's
+Elgar
+Elgar's
+Eli
+Eli's
+Elias
+Elijah
+Elijah's
+Elinor
+Elinor's
+Eliot
+Eliot's
+Elisa
+Elisa's
+Elisabeth
+Elisabeth's
+Elise
+Elise's
+Eliseo
+Eliseo's
+Elisha
+Elisha's
+Eliza
+Eliza's
+Elizabeth
+Elizabeth's
+Elizabethan
+Elizabethans
+Ella
+Ella's
+Ellen
+Ellen's
+Ellesmere
+Ellesmere's
+Ellie
+Ellie's
+Ellington
+Ellington's
+Elliot
+Elliot's
+Elliott
+Elliott's
+Ellis
+Ellison
+Ellison's
+Elma
+Elma's
+Elmer
+Elmer's
+Elmo
+Elmo's
+Elnath
+Elnath's
+Elnora
+Elnora's
+Elohim
+Elohim's
+Eloise
+Eloise's
+Eloy
+Eloy's
+Elroy
+Elroy's
+Elsa
+Elsa's
+Elsie
+Elsie's
+Elsinore
+Elsinore's
+Eltanin
+Eltanin's
+Elton
+Elton's
+Elul
+Elul's
+Elva
+Elva's
+Elvia
+Elvia's
+Elvin
+Elvin's
+Elvira
+Elvira's
+Elvis
+Elvis's
+Elwood
+Elwood's
+Elysian
+Elysium
+Elysium's
+Elysiums
+Elys�e
+Elys�e's
+Emacs
+Emacs's
+Emanuel
+Emanuel's
+Emerson
+Emerson's
+Emery
+Emery's
+Emil
+Emil's
+Emile
+Emile's
+Emilia
+Emilia's
+Emilio
+Emilio's
+Emily
+Emily's
+Emma
+Emma's
+Emmanuel
+Emmanuel's
+Emmett
+Emmett's
+Emmies
+Emmy
+Emmy's
+Emory
+Emory's
+Encarta
+Encarta's
+Endymion
+Endymion's
+Eng
+Eng's
+Engels
+England
+England's
+English
+English's
+Englished
+Englisher
+Englishes
+Englishing
+Englishman
+Englishman's
+Englishmen
+Englishwoman
+Englishwoman's
+Englishwomen
+Enid
+Enid's
+Enif
+Enif's
+Eniwetok
+Eniwetok's
+Enkidu
+Enkidu's
+Enoch
+Enoch's
+Enos
+Enrico
+Enrico's
+Enrique
+Enrique's
+Enron
+Enron's
+Enterprise
+Enterprise's
+Eocene
+Epcot
+Epcot's
+Ephesian
+Ephesus
+Ephesus's
+Ephraim
+Ephraim's
+Epictetus
+Epictetus's
+Epicurean
+Epicurus
+Epicurus's
+Epimethius
+Epimethius's
+Epiphanies
+Epiphany
+Epiphany's
+Episcopal
+Episcopalian
+Episcopalians
+Episcopals
+Epsom
+Epsom's
+Epstein
+Epstein's
+Equuleus
+Equuleus's
+Er
+Er's
+Erasmus
+Erasmus's
+Erato
+Erato's
+Eratosthenes
+Eratosthenes's
+Erebus
+Erebus's
+Erector
+Erhard
+Erhard's
+Eric
+Eric's
+Erica
+Erica's
+Erich
+Erich's
+Erick
+Erick's
+Ericka
+Ericka's
+Erickson
+Erickson's
+Ericson's
+Eridanus
+Eridanus's
+Erie
+Erie's
+Eries
+Erik
+Erik's
+Erika
+Erika's
+Erin
+Erin's
+Eris
+Erises
+Eritrea
+Eritrea's
+Erlenmeyer
+Erlenmeyer's
+Erma
+Erma's
+Erna
+Erna's
+Ernest
+Ernest's
+Ernestine
+Ernestine's
+Ernesto
+Ernesto's
+Ernie
+Ernie's
+Ernst
+Ernst's
+Eros
+Eros's
+Eroses
+Errol
+Errol's
+Erse
+Erse's
+ErvIn
+ErvIn's
+Erwin
+Erwin's
+Es
+Esau
+Esau's
+Escher
+Escher's
+Escherichia
+Escherichia's
+Eskimo
+Eskimo's
+Eskimos
+Esmeralda
+Esmeralda's
+Esperanto
+Esperanto's
+Esperanza
+Esperanza's
+Espinoza
+Espinoza's
+Esq
+Esq's
+Essen
+Essen's
+Essene
+Essene's
+Essequibo
+Essequibo's
+Essex
+Essex's
+Essie
+Essie's
+Establishment
+Establishment's
+Establishments
+Esteban
+Esteban's
+Estela
+Estela's
+Estella
+Estella's
+Estelle
+Estelle's
+Ester
+Ester's
+Esterh�zy
+Esterh�zy's
+Estes
+Esther
+Esther's
+Estonia
+Estonia's
+Estonian
+Estonians
+Estrada
+Estrada's
+Ethan
+Ethan's
+Ethel
+Ethel's
+Ethelred
+Ethelred's
+Ethernet
+Ethiopia
+Ethiopia's
+Ethiopian
+Ethiopians
+Etna
+Etna's
+Eton
+Eton's
+Etruria
+Etruria's
+Etruscan
+Etruscan's
+Etruscans
+Etta
+Etta's
+Eu
+Eu's
+Eucharist
+Eucharist's
+Eucharistic
+Eucharists
+Euclid
+Euclid's
+Eugene
+Eugene's
+Eugenia
+Eugenia's
+Eugenie
+Eugenie's
+Eugenio
+Eugenio's
+Eula
+Eula's
+Euler
+Euler's
+Eumenides
+Eunice
+Eunice's
+Euphrates
+Euphrates's
+Eurasia
+Eurasia's
+Eurasian
+Eurasians
+Euripides
+Euripides's
+Eurodollar
+Eurodollar's
+Eurodollars
+Europa
+Europa's
+Europe
+Europe's
+European
+Europeans
+Eurydice
+Eurydice's
+Eustachian
+Eustachian's
+Euterpe
+Euterpe's
+Eva
+Eva's
+Evan
+Evan's
+Evangelina
+Evangelina's
+Evangeline
+Evangeline's
+Evans
+Evansville
+Evansville's
+Eve
+Eve's
+Evelyn
+Evelyn's
+Evenki
+EverReady
+EverReady's
+Everest
+Everest's
+Everett
+Everett's
+Everette
+Everette's
+Everglades
+Evert
+Evert's
+Evian
+Evian's
+Evita
+Evita's
+Ewing
+Ewing's
+Excalibur
+Excalibur's
+Excedrin
+Excedrin's
+Excellencies
+Excellency
+Excellency's
+Exercycle
+Exocet
+Exocet's
+Exodus
+Exodus's
+Exxon
+Exxon's
+Eyck
+Eyck's
+Eyre
+Eyre's
+Eysenck
+Eysenck's
+Ezekiel
+Ezekiel's
+Ezra
+Ezra's
+F
+F's
+FAQ
+FAQs
+FBI
+FDR
+FDR's
+FM
+FMs
+FNMA
+FNMA's
+FUD
+FUDs
+FYI
+Faberg�
+Fabian
+Faeroe
+Faeroe's
+Fafnir
+Fafnir's
+Fagin
+Fagin's
+Fahd
+Fahd's
+Fahrenheit
+Fahrenheits
+Fairbanks
+Faisal
+Faisal's
+Faisalabad
+Faith
+Faith's
+Falasha
+Falasha's
+Falkland
+Falkland's
+Falklands
+Fallopian
+Fallopian's
+Falstaff
+Falstaff's
+Falwell
+Falwell's
+Fannie
+Fannie's
+Fanny
+Fanny's
+Faraday
+Faraday's
+Fargo
+Fargo's
+Farley
+Farley's
+Farmer
+Farmer's
+Farragut
+Farragut's
+Farrakhan
+Farrakhan's
+Farrell
+Farrell's
+Farrow
+Farrow's
+Farsi
+Fassbinder
+Fassbinder's
+Fatah
+Fatah's
+Fates
+Father
+Father's
+Fathers
+Fatima
+Fatima's
+Fatimid
+Fatimid's
+Faulkner
+Faulkner's
+Faulknerian
+Fauntleroy
+Fauntleroy's
+Faust
+Faust's
+Faustian
+Faustino
+Faustino's
+Faustus
+Faustus's
+Fawkes
+Fawkes's
+Fay
+Fay's
+Faye
+Faye's
+Fe
+Fe's
+Feb
+Feb's
+Februaries
+February
+February's
+Fed
+Fed's
+FedEx
+Federalist
+Federico
+Federico's
+Feds
+Felecia
+Felecia's
+Felice
+Felice's
+Felicia
+Felicia's
+Felicity
+Felicity's
+Felipe
+Felipe's
+Felix
+Felix's
+Fellini
+Fellini's
+Fenian
+Fenian's
+Ferber
+Ferber's
+Ferdinand
+Ferdinand's
+Fergus
+Fergus's
+Ferguson
+Ferguson's
+Ferlinghetti
+Ferlinghetti's
+Fermat
+Fermat's
+Fermi
+Fermi's
+Fern
+Fern's
+Fernandez
+Fernandez's
+Fernando
+Fernando's
+Ferrari
+Ferrari's
+Ferraro
+Ferraro's
+Ferrell
+Ferrell's
+Ferris
+Feynman
+Feynman's
+Fez
+Fez's
+Fiat
+Fiat's
+Fiberglas
+Fiberglas's
+Fibonacci
+Fibonacci's
+Fichte
+Fichte's
+Fidel
+Fidel's
+Fido
+Fido's
+Fielding
+Fielding's
+Fields
+Figaro
+Figaro's
+Figueroa
+Figueroa's
+Fiji
+Fiji's
+Fijian
+Fijian's
+Fijians
+Filipino
+Filipino's
+Filipinos
+Fillmore
+Fillmore's
+Filofax
+Finch
+Finch's
+Finland
+Finland's
+Finley
+Finley's
+Finn
+Finn's
+Finnbogadottir
+Finnbogadottir's
+Finnegan
+Finnegan's
+Finnish
+Finns
+Fiona
+Fiona's
+Firestone
+Firestone's
+Fischer
+Fischer's
+Fisher
+Fisher's
+Fisk
+Fisk's
+Fitch
+Fitch's
+Fitzgerald
+Fitzgerald's
+Fitzpatrick
+Fitzpatrick's
+Fitzroy
+Fitzroy's
+Fizeau
+Fizeau's
+Fla
+Fla's
+Flanagan
+Flanagan's
+Flanders
+Flanders's
+Flatt
+Flatt's
+Flaubert
+Flaubert's
+Fleischer
+Fleischer's
+Fleming
+Fleming's
+Flemings
+Flemish
+Flemish's
+Fletcher
+Fletcher's
+Flint
+Flint's
+Flintstones
+Flo
+Flo's
+Flora
+Flora's
+Florence
+Florence's
+Florentine
+Flores
+Florida
+Florida's
+Floridan
+Florine
+Florine's
+Florsheim
+Florsheim's
+Flory
+Flory's
+Flossie
+Flossie's
+Flowers
+Floyd
+Floyd's
+Flynn
+Flynn's
+Fm
+Fm's
+Foch
+Foch's
+Fokker
+Fokker's
+Foley
+Foley's
+Folgers
+Folsom
+Fomalhaut
+Fomalhaut's
+Fonda
+Fonda's
+Foosball
+Foosball's
+Forbes
+Forbes's
+Ford
+Ford's
+Foreman
+Foreman's
+Forest
+Forest's
+Forester
+Forester's
+Formica
+Formica's
+Formicas
+Formosa
+Formosa's
+Formosan
+Forrest
+Forrest's
+Forster
+Forster's
+Fortaleza
+Fortaleza's
+Foster
+Foster's
+Fotomat
+Fotomat's
+Foucault
+Foucault's
+Fourier
+Fourier's
+Fourneyron
+Fourneyron's
+Fowler
+Fowler's
+Fox
+Fox's
+Fr
+Fr's
+Fragonard
+Fragonard's
+Fran
+Fran's
+France
+France's
+Frances
+Francesca
+Francesca's
+Francine
+Francine's
+Francis
+Francisca
+Francisca's
+Franciscan
+Franciscan's
+Francisco
+Francisco's
+Franck
+Franck's
+Franco
+Franco's
+Francois
+Francois's
+Francoise
+Francoise's
+Franglais
+Franglais's
+Frank
+Frank's
+Frankel
+Frankel's
+Frankenstein
+Frankenstein's
+Frankensteins
+Frankfort
+Frankfort's
+Frankfurt
+Frankfurt's
+Frankfurter
+Frankfurter's
+Frankie
+Frankie's
+Franklin
+Franklin's
+Franks
+Franny
+Franny's
+Franz
+Franz's
+Fraser
+Fraser's
+Frazier
+Frazier's
+Fred
+Fred's
+Freda
+Freda's
+Freddie
+Freddie's
+Freddy
+Freddy's
+Frederic
+Frederic's
+Frederick
+Frederick's
+Fredericton
+Fredericton's
+Fredric
+Fredric's
+Fredrick
+Fredrick's
+Freeman
+Freeman's
+Freemason
+Freemason's
+Freemasonries
+Freemasonry
+Freemasonry's
+Freemasons
+Freetown
+Freetown's
+Freida
+Freida's
+Fremont
+Fremont's
+French
+French's
+Frenched
+Frenches
+Frenching
+Frenchman
+Frenchman's
+Frenchmen
+Frenchwoman
+Frenchwoman's
+Frenchwomen
+Freon
+Freon's
+Fresnel
+Fresnel's
+Fresno
+Fresno's
+Freud
+Freud's
+Freudian
+Freudians
+Frey
+Frey's
+Freya
+Freya's
+Fri
+Fri's
+Friday
+Friday's
+Fridays
+Frieda
+Frieda's
+Friedan
+Friedman
+Friedman's
+Frigga
+Frigga's
+Frigidaire
+Frigidaire's
+Frisbee
+Frisbee's
+Frisbees
+Frisco
+Frisco's
+Frisian
+Frisian's
+Frito
+Frito's
+Fritz
+Fritz's
+Frobisher
+Frobisher's
+Froissart
+Froissart's
+Fromm
+Fromm's
+Fronde
+Fronde's
+Frontenac
+Frontenac's
+Frost
+Frost's
+Frostbelt
+Fry
+Fry's
+Frye
+Frye's
+Fuchs
+Fuchs's
+Fuentes
+Fugger
+Fugger's
+Fuji
+Fuji's
+Fujitsu
+Fujitsu's
+Fujiwara
+Fujiwara's
+Fukuoka
+Fukuoka's
+Fulani
+Fulani's
+Fulbright
+Fulbright's
+Fuller
+Fuller's
+Fulton
+Fulton's
+Funafuti
+Fundy
+Fundy's
+Furtw�ngler
+Furtw�ngler's
+Fushun
+Fushun's
+Fuzhou
+Fuzhou's
+Fuzzbuster
+G
+G's
+GE
+GE's
+GED
+GI
+GIGO
+GMAT
+GNP
+GOP
+GPA
+GTE
+GTE's
+Ga
+Ga's
+Gable
+Gable's
+Gabon
+Gabon's
+Gaborone
+Gaborone's
+Gabriel
+Gabriel's
+Gabriela
+Gabriela's
+Gabrielle
+Gabrielle's
+Gacrux
+Gacrux's
+Gadsden
+Gadsden's
+Gaea
+Gaea's
+Gael
+Gael's
+Gaelic
+Gaelic's
+Gagarin
+Gagarin's
+Gage
+Gage's
+Gail
+Gail's
+Gaines
+Gaines's
+Gainsborough
+Gainsborough's
+Galahad
+Galahad's
+Galahads
+Galapagos
+Galapagos's
+Galatea
+Galatea's
+Galatia
+Galatia's
+Galatians
+Galatians's
+Galbraith
+Galbraith's
+Gale
+Gale's
+Galen
+Galen's
+Galibi
+Galibi's
+Galilean
+Galilean's
+Galilee
+Galilee's
+Galileo
+Galileo's
+Gall
+Gall's
+Gallagher
+Gallagher's
+Gallegos
+Gallegos's
+Gallic
+Gallo
+Gallo's
+Galloway
+Galloway's
+Gallup
+Gallup's
+Galois
+Galois's
+Galsworthy
+Galsworthy's
+Galvani
+Galvani's
+Galveston
+Galveston's
+Gamay
+Gambia
+Gambia's
+Gamble
+Gamble's
+Gamow
+Gamow's
+Gandhi
+Gandhi's
+Gandhian
+Ganesha
+Ganesha's
+Ganges
+Ganges's
+Gangtok
+Gangtok's
+Gantry
+Gantry's
+Ganymede
+Ganymede's
+Gap
+Gap's
+Garbo
+Garbo's
+Garcia
+Garcia's
+Gardner
+Gardner's
+Gareth
+Gareth's
+Garfield
+Garfield's
+Garfunkel
+Garfunkel's
+Gargantua
+Gargantua's
+Garibaldi
+Garibaldi's
+Garland
+Garland's
+Garner
+Garner's
+Garrett
+Garrett's
+Garrick
+Garrick's
+Garrison
+Garrison's
+Garry
+Garry's
+Garth
+Garth's
+Garvey
+Garvey's
+Gary
+Gary's
+Garza
+Garza's
+Gascony
+Gascony's
+Gasser
+Gasser's
+Gates
+Gatling
+Gatling's
+Gatorade
+Gatorade's
+Gatsby
+Gatsby's
+Gatun
+Gatun's
+Gauguin
+Gauguin's
+Gaul
+Gaul's
+Gauls
+Gauss
+Gauss's
+Gaussian
+Gautama
+Gautama's
+Gautier
+Gautier's
+Gavin
+Gavin's
+Gawain
+Gawain's
+Gay
+Gay's
+Gayle
+Gayle's
+Gaza
+Gaza's
+Gaziantep
+Gaziantep's
+Gd
+Gd's
+Gdansk
+Gdansk's
+Ge
+Ge's
+Geffen
+Geffen's
+Gehenna
+Gehenna's
+Gehrig
+Gehrig's
+Geiger
+Geiger's
+Gelbvieh
+Gelbvieh's
+Geller
+Geller's
+Gemini
+Gemini's
+Geminis
+Gen
+Gen's
+Gena
+Gena's
+Genaro
+Genaro's
+Gene
+Gene's
+Genesis
+Genesis's
+Genet
+Genet's
+Geneva
+Geneva's
+Genevieve
+Genevieve's
+Genghis
+Genghis's
+Genoa
+Genoa's
+Genoas
+Gentry
+Gentry's
+Geo
+Geo's
+Geoffrey
+Geoffrey's
+George
+George's
+Georges
+Georgetown
+Georgetown's
+Georgette
+Georgette's
+Georgia
+Georgia's
+Georgian
+Georgians
+Georgina
+Georgina's
+Ger
+Ger's
+Gerald
+Gerald's
+Geraldine
+Geraldine's
+Gerard
+Gerard's
+Gerardo
+Gerardo's
+Gerber
+Gerber's
+Geritol
+Geritol's
+German
+German's
+Germanic
+Germanic's
+Germans
+Germany
+Germany's
+Geronimo
+Geronimo's
+Gerry
+Gerry's
+Gershwin
+Gershwin's
+Gertrude
+Gertrude's
+Gestapo
+Gestapo's
+Gestapos
+Gethsemane
+Gethsemane's
+Getty
+Getty's
+Gettysburg
+Gettysburg's
+Gew�rztraminer
+Ghana
+Ghana's
+Ghanaian
+Ghanaian's
+Ghanaians
+Ghanian's
+Ghats
+Ghats's
+Ghazvanid
+Ghazvanid's
+Ghent
+Ghent's
+Ghibelline
+Ghibelline's
+Giacometti
+Giacometti's
+Giannini
+Giannini's
+Giauque
+Giauque's
+Gibbon
+Gibbon's
+Gibbs
+Gibraltar
+Gibraltar's
+Gibraltars
+Gibson
+Gibson's
+Gide
+Gide's
+Gideon
+Gideon's
+Gielgud
+Gielgud's
+Gienah
+Gienah's
+Gil
+Gil's
+Gila
+Gila's
+Gilbert
+Gilbert's
+Gilberto
+Gilberto's
+Gilchrist
+Gilchrist's
+Gilda
+Gilda's
+Gilead
+Gilead's
+Giles
+Gilgamesh
+Gilgamesh's
+Gill
+Gill's
+Gillespie
+Gillespie's
+Gillette
+Gillette's
+Gilliam
+Gilliam's
+Gillian
+Gillian's
+Gilligan
+Gilligan's
+Gilmore
+Gilmore's
+Gina
+Gina's
+Ginger
+Ginger's
+Gingrich
+Gingrich's
+Ginny
+Ginny's
+Gino
+Gino's
+Ginsberg
+Ginsberg's
+Ginsburg
+Ginsburg's
+Ginsu
+Ginsu's
+Giorgione
+Giorgione's
+Giotto
+Giotto's
+Giovanni
+Giovanni's
+Gipsy's
+Giraudoux
+Giraudoux's
+Gish
+Gish's
+Giuliani
+Giuliani's
+Giuseppe
+Giuseppe's
+Giza
+Giza's
+Gladstone
+Gladstone's
+Gladstones
+Gladys
+Glaser
+Glaser's
+Glasgow
+Glasgow's
+Glass
+Glass's
+Glastonbury
+Glastonbury's
+Glaswegian
+Glaxo
+Glaxo's
+Gleason
+Gleason's
+Glen
+Glen's
+Glenda
+Glenda's
+Glendale
+Glendale's
+Glenlivet
+Glenlivet's
+Glenn
+Glenn's
+Glenna
+Glenna's
+Gloria
+Gloria's
+Gloucester
+Gloucester's
+Glover
+Glover's
+Gnostic
+Gnostic's
+Gnosticism
+Gnosticism's
+Goa
+Goa's
+Gobi
+Gobi's
+God
+God's
+Goddard
+Goddard's
+Godiva
+Godiva's
+Godot
+Godot's
+Godthaab
+Godthaab's
+Godunov
+Godunov's
+Godzilla
+Godzilla's
+Goebbels
+Goebbels's
+Goering
+Goering's
+Goethals
+Goethals's
+Goethe
+Goethe's
+Goff
+Goff's
+Gog
+Gog's
+Gogol
+Gogol's
+Goiania
+Goiania's
+Golan
+Golan's
+Golconda
+Golconda's
+Golda
+Golda's
+Goldberg
+Goldberg's
+Golden
+Golden's
+Goldie
+Goldie's
+Goldilocks
+Goldilocks's
+Golding
+Golding's
+Goldman
+Goldman's
+Goldsmith
+Goldsmith's
+Goldwater
+Goldwater's
+Goldwyn
+Goldwyn's
+Golgi
+Golgi's
+Golgotha
+Golgotha's
+Goliath
+Goliath's
+Goliaths
+Gomez
+Gomez's
+Gomorrah
+Gomorrah's
+Gompers
+Gompers's
+Gomulka
+Gomulka's
+Gondwanaland
+Gondwanaland's
+Gonzales
+Gonzales's
+Gonzalez
+Gonzalez's
+Gonzalo
+Gonzalo's
+Good
+Good's
+Goodall
+Goodall's
+Goodman
+Goodman's
+Goodrich
+Goodrich's
+Goodwill
+Goodwill's
+Goodwin
+Goodwin's
+Goodyear
+Goodyear's
+Gopher
+Gorbachev
+Gordian
+Gordian's
+Gordimer
+Gordon
+Gordon's
+Gore
+Gore's
+Goren
+Goren's
+Gorey
+Gorey's
+Gorgas
+Gorgonzola
+Gorgonzola's
+Gorky
+Gorky's
+Gospel
+Gospel's
+Gospels
+Goth
+Goth's
+Gotham
+Gotham's
+Gothic
+Gothics
+Goths
+Gouda
+Gouda's
+Goudas
+Gould
+Gould's
+Gounod
+Gounod's
+Goya
+Goya's
+Gracchus
+Gracchus's
+Grace
+Grace's
+Graceland
+Graceland's
+Gracie
+Gracie's
+Graciela
+Graciela's
+Grady
+Grady's
+Graffias
+Graffias's
+Grafton
+Grafton's
+Graham
+Graham's
+Grahame
+Grahame's
+Grail
+Grail's
+Grails
+Grammies
+Grammy
+Grampians
+Granada
+Granada's
+Grant
+Grant's
+Grass
+Grass's
+Graves
+Graves's
+Gray
+Gray's
+Grecian
+Grecians
+Greece
+Greece's
+Greek
+Greek's
+Greeks
+Greeley
+Greeley's
+Green
+Green's
+Greene
+Greene's
+Greenland
+Greenland's
+Greenpeace
+Greenpeace's
+Greensboro
+Greensboro's
+Greensleeves
+Greensleeves's
+Greenspan
+Greenspan's
+Greenwich
+Greenwich's
+Greer
+Greer's
+Greg
+Greg's
+Gregg
+Gregg's
+Gregorian
+Gregorio
+Gregorio's
+Gregory
+Gregory's
+Grenada
+Grenada's
+Grenadines
+Grendel
+Grendel's
+Grenoble
+Grenoble's
+Gresham
+Gresham's
+Greta
+Greta's
+Gretchen
+Gretchen's
+Gretel
+Gretel's
+Gretzky
+Gretzky's
+Grey
+Grey's
+Grieg
+Grieg's
+Griffin
+Griffin's
+Griffith
+Griffith's
+Grimes
+Grimm
+Grimm's
+Grinch
+Grinch's
+Gris
+Gris's
+Gromyko
+Gromyko's
+Gropius
+Gropius's
+Gross
+Grosz
+Grosz's
+Grotius
+Grotius's
+Grover
+Grover's
+Grumman
+Grumman's
+Grundy
+Grundy's
+Grus
+Grus's
+Gruyeres
+Gruy�re
+Gr�newald
+Gr�newald's
+Guadalajara
+Guadalajara's
+Guadalcanal
+Guadalcanal's
+Guadalquivir
+Guadalquivir's
+Guadalupe
+Guadalupe's
+Guadeloupe
+Guadeloupe's
+Guallatiri
+Guallatiri's
+Guam
+Guam's
+Guangzhou
+Guantanamo
+Guantanamo's
+Guarani
+Guarani's
+Guarnieri
+Guarnieri's
+Guatemala
+Guatemala's
+Guatemalan
+Guatemalans
+Guayaquil
+Guayaquil's
+Gucci
+Gucci's
+Guelph
+Guelph's
+Guernsey
+Guernsey's
+Guernseys
+Guerra
+Guerra's
+Guerrero
+Guerrero's
+Guevara
+Guevara's
+Guggenheim
+Guggenheim's
+Guiana
+Guiana's
+Guido
+Guillermo
+Guillermo's
+Guinea
+Guinea's
+Guinean
+Guineans
+Guinevere
+Guinevere's
+Guinness
+Guinness's
+Guiyang
+Guizot
+Guizot's
+Gujarat
+Gujarat's
+Gujarati
+Gujarati's
+Gujranwala
+Gujranwala's
+Gullah
+Gullah's
+Gulliver
+Gulliver's
+Gumbel
+Gumbel's
+Gunther
+Gunther's
+Guofeng
+Guofeng's
+Gupta
+Gupta's
+Gurkha
+Gurkha's
+Gus
+Gus's
+Gustav
+Gustav's
+Gustavo
+Gustavo's
+Gustavus
+Gustavus's
+Gutenberg
+Gutenberg's
+Guthrie
+Guthrie's
+Gutierrez
+Gutierrez's
+Guy
+Guy's
+Guyana
+Guyana's
+Guyanese
+Guzman
+Guzman's
+Gwalior
+Gwalior's
+Gwen
+Gwen's
+Gwendoline
+Gwendoline's
+Gwendolyn
+Gwendolyn's
+Gwyn
+Gwyn's
+Gypsies
+Gypsy
+Gypsy's
+G�del
+G�del's
+G�teborg
+G�teborg's
+H
+H's
+HIV
+HMO
+HQ
+Haas
+Haas's
+Habakkuk
+Habakkuk's
+Haber
+Haber's
+Hadar
+Hadar's
+Hades
+Hadrian
+Hadrian's
+Hafiz
+Hafiz's
+Hagar
+Hagar's
+Haggai
+Haggai's
+Hagiographa
+Hagiographa's
+Hague
+Hague's
+Hahn
+Hahn's
+Haifa
+Haifa's
+Haiphong
+Haiphong's
+Haiti
+Haiti's
+Haitian
+Haitians
+Hakka
+Hakka's
+Hakluyt
+Hakluyt's
+Hal
+Hal's
+Haldane
+Haldane's
+Hale
+Hale's
+Haleakala
+Haleakala's
+Haley
+Haley's
+Halifax
+Halifax's
+Hall
+Hall's
+Halley
+Halley's
+Hallie
+Hallie's
+Hallmark
+Hallmark's
+Halloween
+Halloween's
+Halloweens
+Hallstatt
+Halon
+Halon's
+Hals
+Halsey
+Halsey's
+Ham
+Ham's
+Haman
+Haman's
+Hamburg
+Hamburg's
+Hamburgs
+Hamhung
+Hamhung's
+Hamilcar
+Hamilcar's
+Hamill
+Hamill's
+Hamilton
+Hamilton's
+Hamiltonian
+Hamiltonian's
+Hamitic
+Hamitic's
+Hamlet
+Hamlet's
+Hamlin
+Hamlin's
+Hammarskjold
+Hammerstein
+Hammerstein's
+Hammett
+Hammett's
+Hammond
+Hammond's
+Hammurabi
+Hammurabi's
+Hampshire
+Hampshire's
+Hampton
+Hampton's
+Hamsun
+Hamsun's
+Han
+Han's
+Hancock
+Hancock's
+Handel
+Handel's
+Handy
+Handy's
+Haney
+Haney's
+Hangul
+Hangul's
+Hangzhou
+Hank
+Hank's
+Hanna
+Hanna's
+Hannah
+Hannah's
+Hannibal
+Hannibal's
+Hanoi
+Hanoi's
+Hanover
+Hanover's
+Hanoverian
+Hans
+Hansel
+Hansel's
+Hansen
+Hansen's
+Hanson
+Hanson's
+Hanukkah
+Hanukkah's
+Hanukkahs
+Hapsburg
+Hapsburg's
+Harare
+Harbin
+Harbin's
+Hardin
+Hardin's
+Harding
+Harding's
+Hardy
+Hardy's
+Hargreaves
+Hargreaves's
+Harlan
+Harlan's
+Harlem
+Harlem's
+Harlequin
+Harley
+Harley's
+Harlow
+Harlow's
+Harmon
+Harmon's
+Harold
+Harold's
+Harper
+Harper's
+Harrell
+Harrell's
+Harriet
+Harriet's
+Harriett
+Harriett's
+Harrington
+Harrington's
+Harris
+Harrisburg
+Harrisburg's
+Harrison
+Harrison's
+Harrods
+Harry
+Harry's
+Hart
+Hart's
+Harte
+Harte's
+Hartford
+Hartford's
+Hartline
+Hartline's
+Hartman
+Hartman's
+Harvard
+Harvard's
+Harvey
+Harvey's
+Hasbro
+Hasbro's
+Hasidim
+Hastings
+Hastings's
+Hatfield
+Hatfield's
+Hathaway
+Hathaway's
+Hatsheput
+Hatsheput's
+Hatteras
+Hatteras's
+Hattie
+Hattie's
+Hauptmann
+Hauptmann's
+Hausa
+Hausa's
+Hausdorff
+Hausdorff's
+Havana
+Havana's
+Havanas
+Havarti
+Havel
+Havel's
+Havoline
+Havoline's
+Hawaii
+Hawaii's
+Hawaiian
+Hawaiians
+Hawking
+Hawkins
+Hawkins's
+Hawthorne
+Hawthorne's
+Hay
+Hay's
+Hayden
+Hayden's
+Haydn
+Haydn's
+Hayes
+Haynes
+Hays
+Haywood
+Haywood's
+Hazel
+Hazel's
+Hazlitt
+Hazlitt's
+He
+He's
+Head
+Head's
+Hearst
+Hearst's
+Heath
+Heath's
+Heather
+Heather's
+Heaviside
+Heaviside's
+Hebe
+Hebe's
+Hebert
+Hebert's
+Hebraic
+Hebrew
+Hebrew's
+Hebrews
+Hebrides
+Hebrides's
+Hecate
+Hecate's
+Hector
+Hector's
+Hecuba
+Hecuba's
+Heep
+Heep's
+Hefner
+Hefner's
+Hegel
+Hegel's
+Hegelian
+Hegira
+Hegira's
+Heidegger
+Heidegger's
+Heidelberg
+Heidelberg's
+Heidi
+Heidi's
+Heifetz
+Heifetz's
+Heimlich
+Heimlich's
+Heine
+Heine's
+Heineken
+Heineken's
+Heinlein
+Heinlein's
+Heinrich
+Heinrich's
+Heinz
+Heisenberg
+Heisenberg's
+Heisman
+Heisman's
+Helen
+Helen's
+Helena
+Helena's
+Helene
+Helene's
+Helga
+Helga's
+Helicon
+Helicon's
+Heliopolis
+Heliopolis's
+Helios
+Helios's
+Hell's
+Hellenic
+Hellenism
+Hellenism's
+Hellenisms
+Hellenistic
+Hellenization
+Hellenization's
+Hellenize
+Heller
+Heller's
+Hellespont
+Hellespont's
+Hellman
+Hellman's
+Helmholtz
+Helmholtz's
+Helsinki
+Helsinki's
+Helvetius
+Helvetius's
+Hemingway
+Hemingway's
+Hench
+Hench's
+Henderson
+Henderson's
+Hendricks
+Hendrix
+Hendrix's
+Henley
+Henley's
+Henri
+Henri's
+Henrietta
+Henrietta's
+Henry
+Henry's
+Hensley
+Hensley's
+Henson
+Henson's
+Hepburn
+Hepburn's
+Hephaestus
+Hephaestus's
+Hepplewhite
+Hera
+Hera's
+Heraclitus
+Heraclitus's
+Herbart
+Herbart's
+Herbert
+Herbert's
+Herculaneum
+Herculaneum's
+Hercules
+Herder
+Herder's
+Hereford
+Hereford's
+Herero
+Herero's
+Heriberto
+Heriberto's
+Herman
+Herman's
+Hermaphroditus
+Hermaphroditus's
+Hermes
+Herminia
+Herminia's
+Hermitage
+Hermitage's
+Hermite
+Hermite's
+Hermosillo
+Hermosillo's
+Hernandez
+Hernandez's
+Herod
+Herod's
+Herodotus
+Herodotus's
+Herrera
+Herrera's
+Herrick
+Herrick's
+Herring
+Herring's
+Herschel
+Herschel's
+Hersey
+Hersey's
+Hershel
+Hershel's
+Hershey
+Hershey's
+Hertz
+Hertz's
+Hertzsprung
+Hertzsprung's
+Herzegovina
+Herzegovina's
+Herzl
+Herzl's
+Heshvan
+Heshvan's
+Hesiod
+Hesiod's
+Hesperus
+Hesperus's
+Hess
+Hess's
+Hesse
+Hesse's
+Hessian
+Hessian's
+Hester
+Hester's
+Heston
+Heston's
+Hettie
+Hettie's
+Hewitt
+Hewitt's
+Hewlett
+Hewlett's
+Heyerdahl
+Heyerdahl's
+Heywood
+Heywood's
+Hezbollah
+Hezbollah's
+Hezekiah
+Hezekiah's
+Hf
+Hf's
+Hg
+Hg's
+Hialeah
+Hialeah's
+Hiawatha
+Hiawatha's
+Hibernia
+Hibernia's
+Hickman
+Hickman's
+Hickok
+Hickok's
+Hicks
+Hicks's
+Hieronymus
+Hieronymus's
+Higgins
+Higgins's
+Highlander
+Highlander's
+Highlanders
+Highness
+Highness's
+Hilario
+Hilario's
+Hilary
+Hilary's
+Hilbert
+Hilbert's
+Hilda
+Hilda's
+Hildebrand
+Hildebrand's
+Hilfiger
+Hilfiger's
+Hill
+Hill's
+Hillary
+Hillary's
+Hillel
+Hillel's
+Hilton
+Hilton's
+Himalaya
+Himalaya's
+Himalayas
+Himmler
+Himmler's
+Hinayana
+Hinayana's
+Hindemith
+Hindemith's
+Hindenburg
+Hindenburg's
+Hindi
+Hindi's
+Hindu
+Hindu's
+Hinduism
+Hinduism's
+Hinduisms
+Hindus
+Hindustan
+Hindustan's
+Hindustani
+Hindustani's
+Hines
+Hines's
+Hinton
+Hinton's
+Hipparchus
+Hipparchus's
+Hippocrates
+Hippocrates's
+Hippocratic
+Hiram
+Hiram's
+Hirobumi
+Hirobumi's
+Hirohito
+Hirohito's
+Hiroshima
+Hiroshima's
+Hispanic
+Hispanics
+Hispaniola
+Hispaniola's
+Hiss
+Hiss's
+Hitachi
+Hitachi's
+Hitchcock
+Hitchcock's
+Hitler
+Hitler's
+Hitlers
+Hittite
+Hittite's
+Hmong
+Ho
+Ho's
+Hobart
+Hobart's
+Hobbes
+Hobbes's
+Hobbs
+Hobbs's
+Hockney
+Hockney's
+Hodge
+Hodge's
+Hodges
+Hodgkin
+Hodgkin's
+Hoff
+Hoff's
+Hoffa
+Hoffa's
+Hoffman
+Hoffman's
+Hofstadter
+Hofstadter's
+Hogan
+Hogan's
+Hogarth
+Hogarth's
+Hogwarts
+Hogwarts's
+Hohenlohe
+Hohenlohe's
+Hohenstaufen
+Hohenstaufen's
+Hohenzollern
+Hohenzollern's
+Hohhot
+Hohhot's
+Hohokam
+Hokkaido
+Hokkaido's
+Hokusai
+Hokusai's
+Holbein
+Holbein's
+Holcomb
+Holcomb's
+Holden
+Holden's
+Holder
+Holder's
+Holiday
+Holiday's
+Holland
+Holland's
+Hollands
+Hollerith
+Hollerith's
+Holley
+Holley's
+Hollie
+Hollie's
+Hollis
+Holloway
+Holloway's
+Holly
+Holly's
+Hollywood
+Hollywood's
+Holman
+Holman's
+Holmes
+Holocaust
+Holocene
+Holst
+Holst's
+Holstein
+Holstein's
+Holsteins
+Holt
+Holt's
+Homer
+Homer's
+Homeric
+Hon
+Hon's
+Honda
+Honda's
+Honduran
+Hondurans
+Honduras
+Honduras's
+Honecker
+Honecker's
+Honeywell
+Honeywell's
+Honiara
+Honiara's
+Honolulu
+Honolulu's
+Honshu
+Honshu's
+Hood
+Hood's
+Hooke
+Hooke's
+Hooker
+Hooker's
+Hooper
+Hooper's
+Hoosier
+Hoosier's
+Hooters
+Hooters's
+Hoover
+Hoover's
+Hoovers
+Hope
+Hope's
+Hopewell
+Hopewell's
+Hopi
+Hopi's
+Hopkins
+Hopkins's
+Hopper
+Hopper's
+Horace
+Horace's
+Horacio
+Horacio's
+Horatio
+Horatio's
+Hormel
+Hormel's
+Hormuz
+Hormuz's
+Horn
+Horn's
+Hornblower
+Hornblower's
+Horne
+Horne's
+Horowitz
+Horowitz's
+Horthy
+Horthy's
+Horton
+Horton's
+Horus
+Horus's
+Hosea
+Hosea's
+Hotpoint
+Hotpoint's
+Hottentot
+Hottentot's
+Houdini
+Houdini's
+House
+House's
+Housman
+Housman's
+Houston
+Houston's
+Houyhnhnm
+Houyhnhnm's
+Howard
+Howard's
+Howe
+Howe's
+Howell
+Howell's
+Howells
+Hoyle
+Hoyle's
+Hrothgar
+Hrothgar's
+Huang
+Huang's
+Hubbard
+Hubbard's
+Hubble
+Hubble's
+Huber
+Huber's
+Hubert
+Hubert's
+Huck
+Huck's
+Hudson
+Hudson's
+Huerta
+Huerta's
+Huey
+Huey's
+Huff
+Huff's
+Huffman
+Huffman's
+Huggins
+Hugh
+Hugh's
+Hughes
+Hugo
+Hugo's
+Huguenot
+Huguenot's
+Huguenots
+Hui
+Hui's
+Huitzilopitchli
+Huitzilopitchli's
+Hull
+Hull's
+Humberto
+Humberto's
+Humboldt
+Humboldt's
+Hume
+Hume's
+Humphrey
+Humphrey's
+Humvee
+Hun
+Hun's
+Hung
+Hung's
+Hungarian
+Hungarian's
+Hungarians
+Hungary
+Hungary's
+Huns
+Hunt
+Hunt's
+Hunter
+Hunter's
+Huntington
+Huntington's
+Huntley
+Huntley's
+Huntsville
+Huntsville's
+Hurley
+Hurley's
+Huron
+Huron's
+Hurons
+Hurst
+Hurst's
+Hus
+Hussein
+Hussein's
+Husserl
+Husserl's
+Hussite
+Hussite's
+Huston
+Huston's
+Hutchinson
+Hutchinson's
+Hutton
+Hutton's
+Hutu
+Hutu's
+Huxley
+Huxley's
+Huygens
+Huygens's
+Hyades
+Hyde
+Hyde's
+Hyderabad
+Hyderabad's
+Hydra
+Hydra's
+Hymen
+Hymen's
+Hyperion
+Hyperion's
+Hyundai
+Hyundai's
+Hz
+H�loise
+H�loise's
+I
+I'd
+I'll
+I'm
+I've
+IBM
+IBM's
+ID
+IDs
+IMHO
+INS
+IOU
+IQ
+IRA
+IRAs
+IRS
+IV
+IVs
+Iaccoca
+Iaccoca's
+Iago
+Iago's
+Ian
+Ian's
+Iapetus
+Iapetus's
+Ibadan
+Ibadan's
+Iberia
+Iberia's
+Iberian
+Iberian's
+Ibiza
+Ibiza's
+Iblis
+Iblis's
+Ibo
+Ibo's
+Ibsen
+Ibsen's
+Icahn
+Icahn's
+Icarus
+Icarus's
+Iceland
+Iceland's
+Icelander
+Icelander's
+Icelanders
+Icelandic
+Ida
+Ida's
+Idaho
+Idaho's
+Idahoan
+Idahoans
+Idahoes
+Idahos
+Ieyasu
+Ieyasu's
+Ignacio
+Ignacio's
+Ignatius
+Ignatius's
+Igor
+Igor's
+Iguassu
+Iguassu's
+Ijsselmeer
+Ijsselmeer's
+Ike
+Ike's
+Ikhnaton
+Ikhnaton's
+Ila
+Ila's
+Ilene
+Ilene's
+Iliad
+Iliad's
+Ill
+Ill's
+Illinois
+Illinois's
+Illuminati
+Ilyushin
+Ilyushin's
+Imelda
+Imelda's
+Imodium
+Imodium's
+Imogene
+Imogene's
+Imus
+Imus's
+In
+In's
+Ina
+Ina's
+Inc
+Inc's
+Inca
+Inca's
+Incas
+Inchon
+Inchon's
+Ind
+Ind's
+Independence
+Independence's
+India
+India's
+Indian
+Indian's
+Indiana
+Indiana's
+Indianan
+Indianans
+Indianapolis
+Indianapolis's
+Indians
+Indies
+Indira
+Indira's
+Indochina
+Indochina's
+Indochinese
+Indonesia
+Indonesia's
+Indonesian
+Indonesians
+Indore
+Indore's
+Indra
+Indra's
+Indus
+Indus's
+Indy
+Indy's
+Ines
+Inez
+Inez's
+Inge
+Inge's
+Inglewood
+Inglewood's
+Ingram
+Ingram's
+Ingres
+Ingres's
+Ingrid
+Ingrid's
+Innocent
+Innocent's
+Inonu
+Inonu's
+Inquisition
+Inquisition's
+Instamatic
+Instamatic's
+Intel
+Intel's
+Intelsat
+Intelsat's
+Internationale
+Internationale's
+Internet
+Internets
+Interpol
+Interpol's
+Inuit
+Inuit's
+Inuits
+Inuktitut
+Inuktitut's
+Invar
+Invar's
+Io
+Io's
+Ionesco
+Ionesco's
+Ionian
+Ionian's
+Ionic
+Ionics
+Iowa
+Iowa's
+Iowan
+Iowans
+Iowas
+Iphigenia
+Iphigenia's
+Iqaluit
+Iqaluit's
+Iqbal
+Iqbal's
+Iquitos
+Iquitos's
+Ir
+Ir's
+Ira
+Ira's
+Iran
+Iran's
+Iranian
+Iranian's
+Iranians
+Iraq
+Iraq's
+Iraqi
+Iraqi's
+Iraqis
+Ireland
+Ireland's
+Irene
+Irene's
+Iris
+Irish
+Irisher
+Irishman
+Irishman's
+Irishmen
+Irishwoman
+Irishwoman's
+Irishwomen
+Irkutsk
+Irkutsk's
+Irma
+Irma's
+Iroquoian
+Iroquoian's
+Iroquois
+Iroquois's
+Irrawaddy
+Irrawaddy's
+Irtish
+Irtish's
+Irvin
+Irvin's
+Irving
+Irving's
+Irwin
+Irwin's
+Isaac
+Isaac's
+Isabel
+Isabel's
+Isabella
+Isabella's
+Isabelle
+Isabelle's
+Isaiah
+Isaiah's
+Iscariot
+Iscariot's
+Isfahan
+Isfahan's
+Isherwood
+Isherwood's
+Ishim
+Ishim's
+Ishmael
+Ishmael's
+Ishtar
+Ishtar's
+Isiah
+Isiah's
+Isidro
+Isidro's
+Isis
+Isis's
+Islam
+Islam's
+Islamabad
+Islamabad's
+Islamic
+Islamics
+Islams
+Ismael
+Ismael's
+Ismail
+Ismail's
+Isolde
+Isolde's
+Ispell
+Ispell's
+Israel
+Israel's
+Israeli
+Israeli's
+Israelis
+Israelite
+Israelite's
+Israelites
+Israels
+Issac
+Issac's
+Issachar
+Issachar's
+Istanbul
+Istanbul's
+Isuzu
+Isuzu's
+It
+Itaipu
+Itaipu's
+Italian
+Italian's
+Italians
+Italy
+Italy's
+Itasca
+Itasca's
+Ithaca
+Ithaca's
+Ithacan
+Ito
+Ito's
+Iva
+Iva's
+Ivan
+Ivan's
+Ivanhoe
+Ivanhoe's
+Ives
+Ivory
+Ivory's
+Ivy
+Ivy's
+Iyar
+Iyar's
+Izaak
+Izaak's
+Izanagi
+Izanagi's
+Izanami
+Izanami's
+Izhevsk
+Izhevsk's
+Izmir
+Izmir's
+Izod
+Izod's
+Izvestia
+Izvestia's
+J
+J's
+JFK
+JFK's
+Jack
+Jack's
+Jackie
+Jackie's
+Jacklyn
+Jacklyn's
+Jackson
+Jackson's
+Jacksonian
+Jacksonville
+Jacksonville's
+Jacky
+Jacky's
+Jaclyn
+Jaclyn's
+Jacob
+Jacob's
+Jacobean
+Jacobi
+Jacobi's
+Jacobin
+Jacobin's
+Jacobite
+Jacobite's
+Jacobs
+Jacobson
+Jacobson's
+Jacquard
+Jacquard's
+Jacqueline
+Jacqueline's
+Jacquelyn
+Jacquelyn's
+Jacques
+Jacuzzi
+Jacuzzis
+Jagger
+Jagger's
+Jagiellon
+Jagiellon's
+Jaguar
+Jaguar's
+Jahangir
+Jahangir's
+Jaime
+Jaime's
+Jain
+Jain's
+Jainism
+Jainism's
+Jaipur
+Jaipur's
+Jakarta
+Jakarta's
+Jake
+Jake's
+Jamaal
+Jamaal's
+Jamaica
+Jamaica's
+Jamaican
+Jamaicans
+Jamal
+Jamal's
+Jamar
+Jamar's
+Jame
+Jame's
+Jamel
+Jamel's
+James
+Jamestown
+Jamestown's
+Jami
+Jami's
+Jamie
+Jamie's
+Jan
+Jan's
+Jana
+Jana's
+Janacek
+Janacek's
+Jane
+Jane's
+Janell
+Janell's
+Janelle
+Janelle's
+Janet
+Janet's
+Janette
+Janette's
+Janice
+Janice's
+Janie
+Janie's
+Janine
+Janine's
+Janis
+Janis's
+Janissary
+Janissary's
+Janna
+Janna's
+Jannie
+Jannie's
+Jansen
+Jansen's
+Jansenist
+Jansenist's
+Januaries
+January
+January's
+Janus
+Janus's
+Japan
+Japan's
+Japanese
+Japaneses
+Japura
+Japura's
+Jared
+Jared's
+Jarlsberg
+Jarred
+Jarred's
+Jarrett
+Jarrett's
+Jarrod
+Jarrod's
+Jarvis
+Jarvis's
+Jasmine
+Jasmine's
+Jason
+Jason's
+Jasper
+Jasper's
+Jataka
+Jataka's
+Java
+Java's
+Javanese
+Javas
+Javier
+Javier's
+Jaxartes
+Jaxartes's
+Jay
+Jay's
+Jayapura
+Jayapura's
+Jayawardene
+Jayawardene's
+Jaycee
+Jaycee's
+Jaycees
+Jayne
+Jayne's
+Jayson
+Jayson's
+Jean
+Jean's
+Jeanette
+Jeanette's
+Jeanie
+Jeanie's
+Jeanine
+Jeanine's
+Jeanne
+Jeanne's
+Jeannette
+Jeannette's
+Jeannie
+Jeannie's
+Jeannine
+Jeannine's
+Jed
+Jed's
+Jedi
+Jedi's
+Jeep
+Jeeps
+Jeeves
+Jeeves's
+Jeff
+Jeff's
+Jefferey
+Jefferey's
+Jefferson
+Jefferson's
+Jeffersonian
+Jeffery
+Jeffery's
+Jeffrey
+Jeffrey's
+Jeffry
+Jeffry's
+Jehoshaphat
+Jehoshaphat's
+Jehovah
+Jehovah's
+Jekyll
+Jekyll's
+Jenifer
+Jenifer's
+Jenkins
+Jenkins's
+Jenna
+Jenna's
+Jenner
+Jenner's
+Jennie
+Jennie's
+Jennifer
+Jennifer's
+Jennings
+Jennings's
+Jenny
+Jenny's
+Jensen
+Jensen's
+Jephthah
+Jephthah's
+Jerald
+Jerald's
+Jeremiah
+Jeremia

<TRUNCATED>

[04/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
new file mode 100644
index 0000000..9360f0b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/HaloWordProcessor.as
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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;
+
+
+	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(startIndex:int, endIndex:int, replacement:String):void {
+			
+			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/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
new file mode 100644
index 0000000..ea702da
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+	import com.adobe.linguistics.utils.Token;
+	import __AS3__.vec.Vector;
+	import flash.geom.Point;
+	
+	public interface IHighlighter
+	{
+		function drawSquiggles(tokens:Vector.<Token>):void;
+		function clearSquiggles():void;
+		function set offsetPoint(op:Point):void;
+		function get offsetPoint():Point;
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
new file mode 100644
index 0000000..919acbd
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/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(startIndex:int, endIndex:int, replacement:String):void;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
new file mode 100644
index 0000000..f847584
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkHighlighter.as
@@ -0,0 +1,190 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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;
+	use namespace tlf_internal;	
+
+	public class SparkHighlighter implements IHighlighter
+	{
+		
+		private var mTextField:RichEditableText;
+		private var mHighlighter:Shape;
+		/*
+		* offset point:
+		*/
+		private var _offsetPoint:Point;
+
+
+		public function SparkHighlighter( textField:RichEditableText )
+		{
+			if (textField == null ) throw new Error("illegal argument."); 
+			mTextField = textField;
+			mHighlighter = null;
+			this._offsetPoint = new Point(0,0);
+		}
+
+		public function drawSquiggles(tokens:Vector.<Token>):void
+		{
+			spellCheckRange(tokens);
+		}
+		
+		public function clearSquiggles():void
+		{
+			if (mHighlighter) {
+				mTextField.removeChild(mHighlighter);
+				mHighlighter=null;
+			}		
+		}
+
+		public function set offsetPoint(op:Point):void{
+			_offsetPoint = op;
+		}
+		
+		public function get offsetPoint():Point{
+			return _offsetPoint;
+		}
+
+
+
+		// TODO: refactor this code to share with halo components, and support words that cross lines
+		private function spellCheckRange(tokens:Vector.<Token>):void {
+
+			var ta:RichEditableText = mTextField;
+			if (!ta) return;		
+
+			mHighlighter= new Shape();
+			mHighlighter.graphics.clear();
+			
+			for ( var i:int = 0; i< tokens.length; ++i ) {
+				var _token:Token = tokens[i];
+				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;			
+			mTextField.addChild(mHighlighter);	
+			
+
+		}
+		
+		// Draw squiggly line
+		private function drawSquigglyLineForRange(start:Number, end:Number):void
+		{
+			// draw squiggly line
+			var tf:TextFlow = mTextField.textFlow;
+			var tflFirst:TextFlowLine = tf.flowComposer.findLineAtPosition(start);
+			var tflLast:TextFlowLine = tf.flowComposer.findLineAtPosition(end);
+			var tflIndexFirst:int = tf.flowComposer.findLineIndexAtPosition(start);
+			var tflIndexLast:int = tf.flowComposer.findLineIndexAtPosition(end);
+			
+			// Pointer
+			var tflIndex:int = tflIndexFirst;
+			var tfl:TextFlowLine = tflFirst;
+			
+			if (tflIndexFirst == tflIndexLast) {
+				// Draw one line
+				drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart, end - tflFirst.absoluteStart);
+			} else {
+				// Multiple lines (very long word)
+				drawSquigglyLineAtIndex(tflIndexFirst, start - tflFirst.absoluteStart);
+				
+				tflIndex++;
+				while (tflIndex != tflIndexLast) {
+					drawSquigglyLineAtIndex(tflIndex);
+					tflIndex++;
+				}
+				
+				drawSquigglyLineAtIndex(tflIndexLast, 0, end - tflLast.absoluteStart);
+			}
+		}
+		
+		// Draw a squiggly line at specific line for specific index range
+		private function drawSquigglyLineAtIndex(lineIndex:Number, startIndex:Number=0, endIndex:Number=0x7FFFFFFF):void
+		{
+			var tf:TextFlow = mTextField.textFlow;
+			var tfl:TextFlowLine = tf.flowComposer.getLineAt(lineIndex);
+			var rectLine:Rectangle = tfl.getBounds();
+			if (endIndex == 0x7FFFFFFF) {
+				drawSquigglyLineAtPoint(rectLine.left, rectLine.bottom, rectLine.right - rectLine.left);
+			}
+			else {
+				// Force to have a valid TextLine
+				var tl:TextLine = tfl.getTextLine(true);
+				
+				// TODO: atom index and char index is not matching for some chars, use try/catch to avoid crash
+				try {
+					var rectFirst:Rectangle = tl.getAtomBounds(startIndex);
+					var rectLast:Rectangle = tl.getAtomBounds(endIndex);
+					drawSquigglyLineAtPoint(rectFirst.left + tfl.x, rectLine.bottom, rectLast.right - rectFirst.left);
+				} catch (err:Error)
+				{
+					//TODO: report error
+				}
+			}
+				
+		}
+		// Draw a squiggly from point x,y with given width, the line is drew in mHighlighter 
+		private function drawSquigglyLineAtPoint(x:Number, y:Number, width:Number):void
+		{
+			mHighlighter.graphics.lineStyle(1, 0xfa0707, .65);
+			mHighlighter.graphics.moveTo(x, y);
+			var upDirection:Boolean = false;
+			var offset:uint = 0;
+			var stepLength:uint = 2;
+			for ( var i:uint = 1; offset <= width; i++) {
+				offset = offset + stepLength;
+				if ( upDirection )
+					mHighlighter.graphics.lineTo(x+offset,y);
+				else
+					mHighlighter.graphics.lineTo(x+offset,y+stepLength);
+				upDirection = !upDirection;
+			}	
+		}
+		
+		private function getValidFirstWordIndex():int{
+			var index:int = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, 0 + mTextField.horizontalScrollPosition, 0 + mTextField.verticalScrollPosition);
+			return index;
+
+			
+		}
+		
+		private function getValidLastWordIndex():int{
+			var index:int = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, mTextField.width+mTextField.horizontalScrollPosition, mTextField.height+mTextField.verticalScrollPosition);
+			return index;
+
+		}
+
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
new file mode 100644
index 0000000..81e155b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SparkWordProcessor.as
@@ -0,0 +1,104 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 com.adobe.linguistics.utils.ITokenizer;
+	
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.tlf_internal;
+	
+	import spark.components.RichEditableText;
+	
+	use namespace tlf_internal;	
+	
+	public class SparkWordProcessor implements IWordProcessor
+	{
+		private var mTextField:RichEditableText;
+
+		public function SparkWordProcessor(textField:RichEditableText)
+		{
+			if (textField == null ) throw new Error("illegal argument."); 
+			mTextField = textField;
+		}
+		
+		
+		public function replaceText(startIndex:int, endIndex:int, replacement:String):void {
+			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			
+			ta.setFocus();
+			ta.text = ta.text.substr(0, _misspellStart) + replacement + ta.text.substr(_misspellEnd);
+			ta.textFlow;
+			ta.selectRange(_misspellStart + replacement.length, _misspellStart + replacement.length);
+			
+			// 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/a52655ac/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
new file mode 100644
index 0000000..2292a61
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIAPI/src/com/adobe/linguistics/spelling/ui/SpellingHighlighter.as
@@ -0,0 +1,179 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.ui
+{
+	import flash.display.Shape;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.text.TextLineMetrics;
+	
+	import mx.core.IUITextField;
+	import mx.flash.UIMovieClip;
+
+
+	public class SpellingHighlighter extends UIMovieClip
+	{
+		/*
+		* offset point:
+		*/
+		private var _offsetPoint:Point;
+		
+		/*
+		* Target TextField.
+		*/
+		private var _textField:IUITextField;
+		private static var InvalidIndexValue:int = -2;
+		public function SpellingHighlighter(textField:IUITextField) {
+			super();
+			this._textField = textField;
+			this._offsetPoint = new Point(0,0);
+		}
+		
+		public function drawSquigglyLine(firstCharIndex:int, lastCharIndex:int ):void {
+			var validFirstCharIndex:int = getValidFirstCharIndex(firstCharIndex);
+			var validLastCharIndex:int = getValidLastCharIndex(lastCharIndex);
+			if ( validFirstCharIndex == InvalidIndexValue || validLastCharIndex == InvalidIndexValue ){
+				return;
+			}
+			/* draw squiggly line here. */
+			if ( validFirstCharIndex <= validLastCharIndex ) {
+				var firstLine:int = _textField.getLineIndexOfChar(validFirstCharIndex);
+				var lastLine:int = _textField.getLineIndexOfChar(validLastCharIndex);
+				//only one line case.
+				if(lastLine==firstLine)
+				{
+					drawSingleSquigglyLine(validFirstCharIndex, validLastCharIndex);
+					return;
+				}
+				//more than one line.
+				//first line
+				drawSingleSquigglyLine(validFirstCharIndex, _textField.getLineOffset(firstLine)+_textField.getLineLength(firstLine)-1);
+				//middle....
+				for(var i:int=firstLine+1;i<lastLine;i++)
+				{
+					drawSingleSquigglyLine(_textField.getLineOffset(i), _textField.getLineOffset(i)+_textField.getLineLength(i)-1);
+				}
+				//last lines.
+				drawSingleSquigglyLine(_textField.getLineOffset(lastLine), validLastCharIndex);
+			}
+		}
+		
+		public function drawSingleSquigglyLine(firstCharIndex:int, lastCharIndex:int ):void {
+			var firstLine:int = _textField.getLineIndexOfChar(firstCharIndex);
+			var lastLine:int = _textField.getLineIndexOfChar(lastCharIndex);
+			if ( firstLine != lastLine ) {
+				return;
+			}else {
+				var rect1:Rectangle = _textField.getCharBoundaries(firstCharIndex);
+				var rect2:Rectangle = _textField.getCharBoundaries(lastCharIndex);
+				var x:Number = rect1.x+_offsetPoint.x - _textField.scrollH;
+				var y:Number = rect1.y + rect1.height + 2;
+				var width:Number = rect2.x+rect2.width-rect1.x;
+				
+				// Avoid drawing outside the textField
+				if (x<0) 
+				{
+					if (x+width > 0) {
+						width += x;
+						x = 0;
+					} 
+					else
+						return;
+				}
+				if (x+width > _textField.width) 
+				{
+					if (x < _textField.width) {
+						width = textField.width - x;
+					} 	
+					else
+						return;
+				}
+				
+				// The rectangle that bound the string you want
+				// actual work here.
+				var myShape:Shape = new Shape();
+				myShape.graphics.clear();
+				//myShape.graphics.beginFill(0x0099CC, .35); 
+				myShape.graphics.lineStyle(1, 0xfa0707, .65);
+				myShape.graphics.moveTo(x, y);
+				var upDirection:Boolean = false;
+				var offset:uint = 0;
+				var stepLength:uint = 2;
+				for ( var i:uint = 1; offset <= width; i++) {
+					offset = offset + stepLength;
+					if ( upDirection )
+						myShape.graphics.lineTo(x+offset,y);
+					else
+						myShape.graphics.lineTo(x+offset,y+stepLength);
+					upDirection = !upDirection;
+				}
+				//myShape.graphics.endFill();
+				this.addChild(myShape);	
+			}
+		}
+		
+		private function getValidFirstCharIndex(firstCharIndex:int):int{
+			if(firstCharIndex<0 || firstCharIndex>_textField.text.length-1) 
+			{
+				return InvalidIndexValue;
+			}
+			var firstLine:Number = _textField.getLineIndexOfChar(firstCharIndex);
+			
+			if(firstLine<_textField.scrollV-1)
+			{
+				firstLine = _textField.scrollV-1;
+				return _textField.getLineOffset(firstLine);
+			}
+			return firstCharIndex;
+		}
+		
+		private function getValidLastCharIndex(lastCharIndex:int):int{
+			if(lastCharIndex<0 || lastCharIndex>_textField.text.length-1) 
+			{
+				return InvalidIndexValue;
+			}
+			var lastLine:Number = _textField.getLineIndexOfChar(lastCharIndex);
+			if(lastLine>_textField.bottomScrollV-1)
+			{
+				lastLine = _textField.bottomScrollV-1;
+				return _textField.getLineOffset(lastLine)+_textField.getLineLength(lastLine)-1;
+			}
+			return lastCharIndex;
+		}
+					
+		public function set textField(tf:IUITextField):void{
+			_textField = tf;
+		}
+		
+		public function get textField():IUITextField{
+			return _textField;
+		}
+		
+		public function set offsetPoint(op:Point):void{
+			_offsetPoint = op;
+		}
+		
+		public function get offsetPoint():Point{
+			return _offsetPoint;
+		}
+
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellUI.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellUI.as b/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellUI.as
new file mode 100644
index 0000000..69c9aab
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellUI.as
@@ -0,0 +1,577 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.IHighlighter;
+    import com.adobe.linguistics.spelling.ui.SparkHighlighter;
+    import com.adobe.linguistics.spelling.ui.HaloWordProcessor;
+    import com.adobe.linguistics.spelling.ui.IWordProcessor;
+    import com.adobe.linguistics.spelling.ui.SparkWordProcessor;
+	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;
+	
+	import spark.components.RichEditableText;
+	import spark.components.TextArea;
+	import spark.components.TextInput;
+	
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.TextFlow;
+	
+	use namespace mx_internal;
+	
+	use namespace tlf_internal;	
+	/**
+	 * UI implementation for spelling.
+	 *
+	 * <p>This class is 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>
+	 *
+	 * @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;
+		private var isSparkComponent:Boolean;
+
+        //New Added below
+		private var mTextField:*;
+		
+		//private var mTextField:RichEditableText;
+
+		private var _dictname:String = new String();			
+		private var _hundict:HunspellDictionary = new HunspellDictionary();		
+		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();
+
+		/**
+		 * Enables the spell checking feature for a UI component.
+		 * 
+		 * <p>Note: This version provides only enabling function but no disabling function.</p>
+		 *
+		 * @param comp	A text editing Flex UI component.
+		 				It can be a <code>TextArea</code>, <code>TextInput</code> or <code>RichTextEditor</code>.
+		 * @param dict	A URL for the dictionary to be used with the <code>SpellChecker.</code>
+		 *
+		 * @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);
+			/*var comp1:UIComponent = txt.parent;
+			var comp2:UIComponent = txt.owner;
+			var comp3:UIComponent = txt.parentApplication;
+			var comp4:UIComponent = txt.parentDocument;
+			var comp5:UIComponent = txt.parentDocument.hostComponent; <--spark parent UICOmponent*/
+			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;
+		}
+
+		// Customize the spelling related entry in spelling contextMenu
+		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 specify 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, "en_US");
+		 * </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;
+			var txt2:RichEditableText = null;
+			if ( (comp == null) || !( (comp is mx.controls.TextArea) || (comp is mx.controls.TextInput) || (comp is RichTextEditor) 
+								|| (comp is spark.components.TextArea) || (comp is spark.components.TextInput) || (comp is spark.components.RichEditableText)) )
+				return null;
+			if ((comp as RichTextEditor) != null) {
+				txt = (comp as RichTextEditor).textArea.getTextField() as TextField;
+			}
+			else if ((comp as mx.controls.TextArea) != null){
+				txt = (comp as mx.controls.TextArea).getTextField() as TextField;
+			}
+			else if ((comp as mx.controls.TextInput) != null) {
+				txt = (comp as mx.controls.TextInput).getTextField() as TextField;
+			}
+			else if ((comp as spark.components.TextArea) != null) {
+                if ((comp as spark.components.TextArea).textDisplay is TextField)
+                    txt = (comp as spark.components.TextArea).textDisplay as TextField;
+                else
+    				txt2 = (comp as spark.components.TextArea).textDisplay as RichEditableText;
+			}
+			else if ((comp as spark.components.TextInput) != null) {
+                if ((comp as spark.components.TextInput).textDisplay is TextField)
+                    txt = (comp as spark.components.TextInput).textDisplay as TextField;
+                else
+    				txt2 = (comp as spark.components.TextInput).textDisplay as RichEditableText;
+			}
+			else if ((comp as spark.components.RichEditableText) !=null) {
+				txt2 = comp as RichEditableText;
+			}
+			else {
+				// do nothing if it's not a valid text component
+				return null;
+			}
+			if (txt != null) 
+				return txt;
+			else 
+				return txt2;
+		}
+		
+		/**
+		 * Constructs a SpellUI object.
+		 *
+		 *	@param	textFiled	A Flex UI component to include spell-check capability
+		 *	@param	dict		A URL for Squiggly spelling dictionary.
+		 *
+		 * @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;
+				//New Added below -- check if text field needs to be extracted from textModel
+				//mTextField = textModel;
+			}else if (textModel is RichEditableText ) {
+				isSparkComponent=true;
+				textModel.setFocus();
+				textModel.selectRange(textModel.text.length, textModel.text.length);
+				//New Added below -- check if text field needs to be extracted from textModel
+				//mTextField = textModel ;
+			}else {
+				// do nothing, we only accept textField and TextFlow here....
+				return;
+			}
+			_actualParent = textModel;
+			mTextField = textModel ;
+									
+			mTextField.addEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);
+			mTextField.addEventListener(FocusEvent.FOCUS_IN, handleFocusIn);
+			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 handleFocusIn(event:FocusEvent):void
+		{
+			_checkLastWord = false;
+			doSpellingJob();
+		}
+		
+		private function handleChangeEvent( event:Event ) :void {
+			_checkLastWord = false;
+			spellCheckScreen(event);
+		}
+		
+		/*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 ( isHaloComponent ) {
+				//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 > end) {
+						rect = new Rectangle(0,0,0,0);
+						break;
+					}
+					numLines += mTextField.getLineMetrics(firstLine).height;
+					firstLine++;
+					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); 
+								
+				hh.offsetPoint = offsetPoint;
+			}
+			
+			var tokenizer:TextTokenizer = new TextTokenizer(mTextField.text.substring(start,end));
+			var tokens:Vector.<Token> = new Vector.<Token>();
+			
+			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{			
+			var index:int;
+			if ( mTextField is TextField ) {
+				index = mTextField.getLineOffset(mTextField.scrollV-1);
+			}else if (mTextField is RichEditableText ) {			
+				// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+				try {
+					index = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, 0 + mTextField.horizontalScrollPosition, 0 + mTextField.verticalScrollPosition);
+				
+				} catch (err:Error)
+				{
+					//TODO: report error
+					index = 0;
+				}
+			}
+			return index;
+		}
+		
+		private function getValidLastWordIndex():int{			
+			var index:int;
+			if ( mTextField is TextField ) {
+				index = mTextField.getLineOffset(mTextField.bottomScrollV-1)+mTextField.getLineLength(mTextField.bottomScrollV-1);
+			}else if (mTextField is RichEditableText ) {	
+				// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+				try {
+					index = SelectionManager.computeSelectionIndex(mTextField.textFlow, mTextField, mTextField, mTextField.width+mTextField.horizontalScrollPosition, mTextField.height+mTextField.verticalScrollPosition);
+				} catch (err:Error)
+				{
+					//TODO: report error
+					index = 0;
+				}
+			}				
+			return index;
+		}
+
+			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
+		{					
+			//_newchecker = new SpellChecker(_hundict);
+			
+			// 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);
+			
+			
+			// 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 if ( isSparkComponent ){
+				hh = new SparkHighlighter( _actualParent);
+				hw = new SparkWordProcessor( _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);
+			mTextField.removeEventListener(FocusEvent.FOCUS_IN, handleFocusIn);
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellingContextMenu.as b/Squiggly/main/AdobeSpellingUIEx/src/com/adobe/linguistics/spelling/SpellingContextMenu.as
new file mode 100644
index 0000000..fc71ce3
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUIEx/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.SpellUI;
+	import com.adobe.linguistics.spelling.framework.SpellingService;
+	import com.adobe.linguistics.spelling.ui.*;
+	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;
+	
+	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:*;
+		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();
+			//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/a52655ac/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
new file mode 100644
index 0000000..4128cd4
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
@@ -0,0 +1,522 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.IHighlighter;
+	import com.adobe.linguistics.spelling.ui.IWordProcessor;
+	import com.adobe.linguistics.spelling.ui.TLFHighlighter;
+	import com.adobe.linguistics.spelling.ui.TLFWordProcessor;
+	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.utils.Dictionary;
+	
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	
+	import flashx.textLayout.tlf_internal;
+	
+	
+	use namespace tlf_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 custom UI component built around TLF TextFlow.  </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>
+	 *
+	 * In order to display Squiggly custom right-click context menu, SpellUIForTLF extends TLF <code>ContainerController</code> class and overrides createContextMenu() method 
+	 * of <code>ContainerController</code>. This could have the following side-effects for a Squiggly client:
+	 * <ul>
+	 * 		<li>In case the Squiggly client application uses a derived controller that inherits from ContainerController class in order to show custom context menu items, Squiggly
+	 * 			context menu will override that. That essentially means that after SpellUIForTLF.enableSpelling() is called, client's own custom right-click menu items, if any, will not be
+	 * 			accessible. </li>
+	 * 		<li>Incase any ContainerController api needs to be called after SpellUIForTLF.enableSpelling() has been called, the client application will need to get the controller objects afresh 
+	 * 			from the TextFlow's FlowComposer. This is needed since SpellUIForTLF replaces ContainerController objects with new SquigglyCustomContainerController(derived from ContainerController) objects. </li> 
+	 * </ul>
+	 * 
+	 * 
+	 * <p><code>SpellUIForTLF</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 SpellUIForTLF
+	{
+		private var hh:IHighlighter;
+		private var hw:IWordProcessor;
+		
+		private var _checkLastWord:Boolean = true;
+		private var _spellingEnabled:Boolean;
+		
+		private var _actualParent:*;
+		
+
+        //New Added below
+		private var mTextFlow:TextFlow;
+		
+		
+		private var _dictname:String = new String();			
+
+		private var _userdict:UserDictionary = null;
+		private var _sharedobj:SharedObject = null;
+		private var scm:SpellingContextMenuForTLF;
+		
+		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();
+
+		/**
+		 * Enables the spell checking feature for a TLF TextFlow. Once a TextFlow 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 TLF TextFlow object
+		 * @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 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/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+
+		public static function enableSpelling(comp:TextFlow, lang:String):void
+		{
+			if ( lang == null ) return;
+			if ( comp==null || _UITable[comp]!=undefined )
+				return;	
+			
+			// TODO: dangerous, is garbage collection going to clear this?
+			_UITable[comp]=new SpellUIForTLF(comp, lang);
+			_parentTable[comp] = comp;
+			_cacheDictTable[comp]=lang;			
+		}	
+	
+		/**
+		 * Set the spelling context menu entries. This uses the ActionScript Object class 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
+		 * to localize the context menu strings.
+		 *  
+		 * @param entries A Object 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.
+		 * 
+		 * @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 actionScript <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 specify 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">
+		 * SpellUIForTLF.spellingConfigUrl = "./config/MySpellingConfig.xml";
+		 * SpellUIForTLF.enableSpelling(textFlow, "en_US");
+		 * </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 TLF TextFlow.
+		 * 
+		 * @param comp	TLF TextFlow object on which to disable spell check.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public static function disableSpelling(comp:TextFlow):void{
+			if ( _UITable[comp] == undefined )
+				return;
+			var _ui:SpellUIForTLF = _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;
+		}
+		
+				
+		/**
+		 * Constructs a SpellUI object.
+		 *  @private
+		 *	@param	textFiled	A Flex UI component to include spell-check capability
+		 *	@param	dict		A URL for Squiggly spelling dictionary.
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */			
+		public function SpellUIForTLF(textModel:TextFlow, lang:String)
+		{		
+		
+			_actualParent = textModel;
+			mTextFlow = textModel;					
+			
+			mTextFlow.addEventListener(flashx.textLayout.events.CompositionCompleteEvent.COMPOSITION_COMPLETE, spellCheckScreen,false, 0,true);
+			//mTextFlow.addEventListener(flashx.textLayout.events.StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, spellCheckScreen);
+			
+			_dictname = lang;			
+			loadConfig();			
+		}
+		
+		private function spellCheckScreen(event:Event):void
+		{
+			doSpellingJob();
+		}
+		
+				
+		/**
+		 @private
+		 (This property is for Squiggly Developer use only.)
+		 */		
+		public function doSpellingJob():void
+		{
+			if (_spellingEnabled == false) return;
+			
+			hh.clearSquiggles();
+			for (var idx:int = 0; idx < mTextFlow.flowComposer.numControllers; idx++)
+			{
+				var testController:ContainerController = mTextFlow.flowComposer.getControllerAt(idx); 
+				//if (getValidFirstWordIndexTLF(testController) != -1) 
+					spellCheckRangeTLF(getValidFirstWordIndexTLF(testController), getValidLastWordIndexTLF(testController));
+			}
+			
+		}
+			
+		
+		private function spellCheckRangeTLF(start:uint, end:uint):void {
+			var tokenizer:TextTokenizer;
+			//hh.clearSquiggles();
+			var tt:TextFlow = mTextFlow;
+			//var currentLeaf:FlowLeafElement = tt.getFirstLeaf();
+			var currentLeaf:FlowLeafElement = tt.findLeaf(start);
+			var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null;
+			while (currentParagraph) { // iterate over all paragraphs in the text flow
+				var paraStart:uint = currentParagraph.getAbsoluteStart();
+				if (paraStart > end)
+					break; 
+				
+				//var offsetPoint:Point = new Point(currentParagraph.paddingLeft, currentParagraph.paddingTop); 
+				//hh.offsetPoint = offsetPoint;
+				tokenizer = new TextTokenizer(currentParagraph.getText().substring());
+				//var tokens:Vector.<Token> = new Vector.<Token>();
+				
+				for ( var token:Token = tokenizer.getFirstToken(); token != tokenizer.getLastToken(); token= tokenizer.getNextToken(token) ) {
+					var result:Boolean=_spellingservice.checkWord(currentParagraph.getText().substring(token.first, token.last));					
+					if (!result){
+						//if (_checkLastWord || (token.last+paraStart != currentParagraph.getText().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+paraStart, token.last+paraStart-1));
+					}
+					
+				}
+				currentParagraph = currentParagraph.getNextParagraph();
+				
+			}
+			//hh.postSpellCheckRange(start, end);
+			//hh.offsetPoint = offsetPoint;
+			//hh.drawSquiggles(tokens);
+		}
+		private function getValidFirstWordIndexTLF(containerController:ContainerController):int{			
+			var index:int;
+					
+			// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+			try {
+				//index = SelectionManager.computeSelectionIndex(mTextFlow, containerController.container, containerController.container, 0 + containerController.horizontalScrollPosition, 0 + containerController.verticalScrollPosition);
+				// SelectionManager.computeSelectionIndex() sometimes gives index as -1. in the same scenarios below logic works better 
+				var tl:TextFlowLine = containerController.getFirstVisibleLine();
+				var firstVisiblePosition:int = tl.absoluteStart;
+				index = firstVisiblePosition;
+				
+			} catch (err:Error)
+			{
+				//TODO: report error
+				index = 0;
+			}
+				
+			return index;
+		}
+		
+		private function getValidLastWordIndexTLF(containerController:ContainerController):int{			
+			var index:int;
+			
+			// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+			try {
+				//index = SelectionManager.computeSelectionIndex(mTextFlow, containerController.container, containerController.container, containerController.container.width+containerController.horizontalScrollPosition, containerController.container.height+containerController.verticalScrollPosition);
+				var tl:TextFlowLine = containerController.getLastVisibleLine();
+				var lastVisiblePosition:int = tl.absoluteStart + tl.textLength;
+				index = lastVisiblePosition;
+			} catch (err:Error)
+			{
+				//TODO: report error
+				index = 0;
+			}
+				
+			return index;
+		}
+		
+
+		private function loadConfig():void{
+			_resource_locale = SpellingConfiguration.resourceTable.getResource(_dictname);
+			
+			if ((_resource_locale != null) || (SpellUIForTLF._configXML != null)) 
+				loadConfigComplete(null);
+			else {	
+				SpellUIForTLF._configXMLLoader.addEventListener(Event.COMPLETE, loadConfigComplete);
+			
+				if (SpellUIForTLF._configXMLLoading == false)
+				{
+					SpellUIForTLF._configXMLLoader.load(new URLRequest(_spellingConfigUrl));
+					SpellUIForTLF._configXMLLoading = true;
+				}
+			}
+		}
+		
+		private function loadConfigComplete(evt:Event):void{
+			if (_resource_locale == null) {
+			if (SpellUIForTLF._configXML == null)
+				SpellUIForTLF._configXML= new XML(evt.target.data);
+			
+				SpellingConfiguration.resourceTable.setResource(_dictname,{rule:SpellUIForTLF._configXML.LanguageResource.(@languageCode==_dictname).@ruleFile, 
+																		dict:SpellUIForTLF._configXML.LanguageResource.(@languageCode==_dictname).@dictionaryFile});
+		}
+                //New Added
+			_spellingservice = new SpellingService(_dictname);
+			_spellingservice.addEventListener(Event.COMPLETE, loadDictComplete);
+			_spellingservice.init();
+		}
+		
+				
+				
+		
+		private function loadDictComplete(evt:Event):void
+		{					
+			//_newchecker = new SpellChecker(_hundict);
+			
+			// Lazy loading the UD only when the main dict is loaded successfully
+			if ((SpellUIForTLF._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);
+				
+				SpellUIForTLF._cache["Squiggly_SO"] = _sharedobj;
+				SpellUIForTLF._cache["Squiggly_UD"] = _userdict;
+			}
+			else 
+			{
+				_sharedobj = SpellUIForTLF._cache["Squiggly_SO"];
+				_userdict = SpellUIForTLF._cache["Squiggly_UD"];
+			}
+			_spellingservice.addUserDictionary(_userdict);
+			
+			
+			// 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;
+			
+			hh = new TLFHighlighter( _actualParent);
+			hw = new TLFWordProcessor( _actualParent);	
+						
+			scm =  new SpellingContextMenuForTLF(hh, hw, _spellingservice, _actualParent, addWordToUserDictionary); 
+			//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);
+			
+			mTextFlow.removeEventListener(flashx.textLayout.events.CompositionCompleteEvent.COMPOSITION_COMPLETE, spellCheckScreen);
+			//mTextFlow.removeEventListener(flashx.textLayout.events.StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, spellCheckScreen);
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellingContextMenuForTLF.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellingContextMenuForTLF.as b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellingContextMenuForTLF.as
new file mode 100644
index 0000000..ccc3c78
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellingContextMenuForTLF.as
@@ -0,0 +1,249 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.SpellUIForTLF;
+	import com.adobe.linguistics.spelling.SquigglyCustomContainerController;
+	import com.adobe.linguistics.spelling.framework.SpellingService;
+	import com.adobe.linguistics.spelling.ui.IHighlighter;
+	import com.adobe.linguistics.spelling.ui.IWordProcessor;
+	import com.adobe.linguistics.spelling.ui.TLFHighlighter;
+	import com.adobe.linguistics.spelling.ui.TLFWordProcessor;
+	import com.adobe.linguistics.utils.TextTokenizer;
+	import com.adobe.linguistics.utils.Token;
+	
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.ui.ContextMenu;
+	import flash.ui.ContextMenuItem;
+	import flash.utils.describeType;
+	import flash.utils.getQualifiedClassName;
+		
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.textLayout.tlf_internal;
+	
+	
+	use namespace tlf_internal;	
+	
+	public class SpellingContextMenuForTLF
+	{
+		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 mTextFlow:TextFlow;
+		private var _ignoreWordFunctionProcessor:Function;
+		private var _misspelledToken:Token;
+		private var _misspelled:String;
+		public function SpellingContextMenuForTLF(textHighlighter:IHighlighter, wordProcessor:IWordProcessor, engine:SpellingService, actualParent:*, func:Function)
+		{
+			
+			if ( textHighlighter == null || wordProcessor == null ||  engine == null) throw new Error("illegal argument."); 
+			mTextHighlighter = textHighlighter;
+			mWordProcessor = wordProcessor;
+			mSpellEngine = engine;
+			mTextFlow = actualParent;
+			
+			
+			var numControllers:int = mTextFlow.flowComposer.numControllers;
+			for (var idx:int = 0; idx < numControllers; idx++)
+			{	
+				var containerController:ContainerController = mTextFlow.flowComposer.getControllerAt(idx);
+				var squigglyContainerController:SquigglyCustomContainerController = new SquigglyCustomContainerController(containerController.container, mTextHighlighter, mWordProcessor, 
+																								mSpellEngine, func, containerController.compositionWidth, containerController.compositionHeight);	
+				copyObject(containerController, squigglyContainerController);
+				mTextFlow.flowComposer.removeController(containerController);
+				containerController = null; // make it null so that the associated memory is garbage collected
+				mTextFlow.flowComposer.addControllerAt(squigglyContainerController, idx);
+				
+			}
+			mTextFlow.flowComposer.updateAllControllers();
+			
+			
+			spellingEnabled = true; //default value
+			//spellingEnabled= mTextHighlighter.spellingEnabled;
+			
+			_ignoreWordFunctionProcessor=null;
+		}
+		
+		/**
+		 * copies a source object to a destination object
+		 * @param sourceObject the source object
+		 * @param destinationObject the destination object
+		 *
+		 */
+		private function copyObject(sourceObject:ContainerController, destinationObject:SquigglyCustomContainerController):void
+		{
+			// check if the objects are not null
+			if((sourceObject) && (destinationObject)) {
+				try
+				{
+					//retrive information about the source object via XML
+					var sourceInfo:XML = describeType(sourceObject);
+					var objectProperty:XML;
+					var propertyName:String;
+					
+					// loop through the properties
+					for each(objectProperty in sourceInfo.variable)
+					{
+						propertyName = objectProperty.@name;
+						if(sourceObject[objectProperty.@name] != null)
+						{
+							if(destinationObject.hasOwnProperty(objectProperty.@name)) {
+								destinationObject[objectProperty.@name] = sourceObject[objectProperty.@name];
+							}
+						}
+					}
+					//loop through the accessors
+					for each(objectProperty in sourceInfo.accessor) {
+						if(objectProperty.@access == "readwrite") {
+							propertyName = objectProperty.@name;
+							if(sourceObject[objectProperty.@name] != null)
+							{
+								if(destinationObject.hasOwnProperty(objectProperty.@name)) {
+									destinationObject[objectProperty.@name] = sourceObject[objectProperty.@name];
+								}
+							}
+						}
+					}
+				}
+				catch (err:*) {
+					;
+				}
+			}
+		}
+		
+		public function cleanUp():void
+		{
+			mTextHighlighter=null;
+			mWordProcessor=null;
+			spellingEnabled = false;
+			_ignoreWordFunctionProcessor=null;
+			
+			var numControllers:int = mTextFlow.flowComposer.numControllers;
+			for (var idx:int = 0; idx < numControllers; idx++)
+			{	
+				 //if (getQualifiedClassName(mTextFlow.flowComposer.getControllerAt(idx)) == "SquigglyCustomContainerController"){
+					 var containerController:ContainerController = mTextFlow.flowComposer.getControllerAt(idx);
+					 //Use try-catch incase some controller not of type SquigglyCustomContainerController comes across
+					 try {
+					 (containerController as SquigglyCustomContainerController).cleanUpContextMenu();
+					 }
+					 catch (err:Error)
+					 {
+						 // TODO: error handling here
+					 }
+				 //}
+				
+			}
+			
+		}
+		
+		public function get contextMenu():ContextMenu {
+			return this._contextMenu;
+		}
+		
+		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);
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[mTextFlow]].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 );
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[mTextFlow]].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));
+			
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[mTextFlow]].spellingEnabled = spellingEnabled;
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[mTextFlow]].doSpellingJob();
+			//spellCheckRange(getValidFirstWordIndex(), getValidLastWordIndex());
+		}
+		private function handleDisableSpellCheck(event:ContextMenuEvent):void
+		{
+			spellingEnabled= false;
+			SpellUIForTLF.UITable[SpellUIForTLF.parentComp[mTextFlow]].spellingEnabled = spellingEnabled;
+			mTextHighlighter.clearSquiggles();
+		}
+				
+	}
+}


[08/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
new file mode 100644
index 0000000..37df37e
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging
+{
+
+import flash.events.IEventDispatcher;
+
+public interface ILogger extends IEventDispatcher
+{
+    function get category():String;
+
+    function log(level:int, message:String, ... rest):void;
+    function debug(message:String, ... rest):void;
+    function error(message:String, ... rest):void;
+
+    function fatal(message:String, ... rest):void;
+    function info(message:String, ... rest):void;
+    function warn(message:String, ... rest):void;
+}
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as
new file mode 100644
index 0000000..47ed7ac
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as
@@ -0,0 +1,39 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging
+{
+public interface ILoggingTarget 
+{
+    function get filters():Array;
+    
+    function set filters(value:Array):void;
+    function get level():int;
+
+    function set level(value:int):void;
+    
+    function get mask():int;
+
+    function addLogger(logger:ILogger):void;
+
+    function removeLogger(logger:ILogger):void;
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
new file mode 100644
index 0000000..e9a720d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
@@ -0,0 +1,210 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging
+{
+	import flash.errors.IllegalOperationError;
+public class Log
+{
+
+    private static var _targetLevel:int = LogEventLevel.NONE;
+        // Initialize target level to a value out of range.
+
+    private static var _loggers:Array;
+
+    private static var _targets:Array = [];
+
+	
+    public static function isFatal():Boolean
+    {
+        return (_targetLevel & LogEventLevel.FATAL) ? true : false;
+    }
+    
+    public static function isError():Boolean
+    {
+        return (_targetLevel & LogEventLevel.ERROR) ? true : false;
+    }
+    
+    public static function isWarn():Boolean
+    {
+        return (_targetLevel & LogEventLevel.WARN) ? true : false;
+    }
+
+    public static function isInfo():Boolean
+    {
+        return (_targetLevel & LogEventLevel.INFO) ? true : false;
+    }
+    
+    public static function isDebug():Boolean
+    {
+        return (_targetLevel & LogEventLevel.DEBUG) ? true : false;
+    }
+
+    public static function addTarget(target:ILoggingTarget):void
+    {
+        if (target)
+        {
+            var filters:Array = target.filters;
+            var logger:ILogger;
+            // need to find what filters this target matches and set the specified
+            // target as a listener for that logger.
+            for (var i:String in _loggers)
+            {
+                if (categoryMatchInFilterList(i, filters))
+                    target.addLogger(ILogger(_loggers[i]));
+            }
+            // if we found a match all is good, otherwise we need to
+            // put the target in a waiting queue in the event that a logger
+            // is created that this target cares about.
+            _targets.push(target);
+            
+            if (_targetLevel == LogEventLevel.NONE)
+                _targetLevel = target.mask;
+            else{
+            	_targetLevel = _targetLevel | target.mask;
+            }
+        }
+        else
+        {
+            throw new IllegalOperationError("addTarget function did not receive null object.");
+        }
+    }
+
+    public static function removeTarget(target:ILoggingTarget):void
+    {
+        if (target)
+        {
+            var filters:Array = target.filters;
+            var logger:ILogger;
+            // Disconnect this target from any matching loggers.
+            for (var i:String in _loggers)
+            {
+                if (categoryMatchInFilterList(i, filters))
+                {
+                    target.removeLogger(ILogger(_loggers[i]));
+                }                
+            }
+            // Remove the target.
+            for (var j:int = 0; j<_targets.length; j++)
+            {
+                if (target == _targets[j])
+                {
+                    _targets.splice(j, 1);
+                    j--;
+                }
+            }
+            resetTargetLevel();
+        }
+        else
+        {
+            throw new IllegalOperationError("addHandle function did not receive null object.");
+        }
+    }
+
+    public static function getLogger(category:String):ILogger
+    {
+        checkCategory(category);
+        if (!_loggers)
+            _loggers = [];
+		var newFlag:Boolean = false;
+        // get the logger for the specified category or create one if it
+        // doesn't exist
+        var result:ILogger = _loggers[category];
+        if (result == null)
+        {
+            result = new LogLogger(category);
+            _loggers[category] = result;
+            newFlag = true;
+        }
+
+        // check to see if there are any targets waiting for this logger.
+        var target:ILoggingTarget;
+        for (var i:int = 0; (i < _targets.length)&&(newFlag); i++)
+        {
+            target = ILoggingTarget(_targets[i]);
+            if (categoryMatchInFilterList(category, target.filters))
+                target.addLogger(result);
+        }
+
+        return result;
+    }
+
+    public static function flush():void
+    {
+        _loggers = [];
+        _targets = [];
+        _targetLevel = LogEventLevel.NONE;
+    }
+
+    public static function hasIllegalCharacters(value:String):Boolean
+    {
+        return value.search(/[\[\]\~\$\^\&\\(\)\{\}\+\?\/=`!@#%,:;'"<>\s]/) != -1;
+    }
+
+    private static function categoryMatchInFilterList(category:String, filters:Array):Boolean
+    {
+        var result:Boolean = false;
+        var filter:String;
+        var index:int = -1;
+        for (var i:uint = 0; i < filters.length; i++)
+        {
+            filter = filters[i];
+            // first check to see if we need to do a partial match
+            // do we have an asterisk?
+            index = filter.indexOf("*");
+
+            if (index == 0)
+                return true;
+
+            index = index < 0 ? index = category.length : index -1;
+
+            if (category.substring(0, index) == filter.substring(0, index))
+                return true;
+        }
+        return false;
+    }
+
+    private static function checkCategory(category:String):void
+    {
+        var message:String;
+        
+        if (category == null || category.length == 0)
+        {
+            throw new IllegalOperationError("checkCategory function did not receive null object.");
+        }
+
+        if (hasIllegalCharacters(category) || (category.indexOf("*") != -1))
+        {
+            throw new IllegalOperationError("checkCategory function did not receive invalid characters.");
+        }
+    }
+    
+    private static function resetTargetLevel():void
+    {	
+    	var res:int = 0;
+        for (var i:int = 0; i < _targets.length; i++)
+        {
+            res = ( res | (_targets[i].mask) );
+        }
+        _targetLevel = res;
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as
new file mode 100644
index 0000000..d90098d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.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.core.logging
+{
+
+import flash.events.Event;
+
+public class LogEvent extends Event
+{
+    public static const eventID:String = "com.adobe.linguistics.spelling.core.logging.LogEvent";
+
+    public static function getLevelString(value:uint):String
+    {
+        switch (value)
+        {
+            case LogEventLevel.INFO:
+			{
+                return "INFO";
+			}
+
+            case LogEventLevel.DEBUG:
+			{
+                return "DEBUG";
+            }
+
+            case LogEventLevel.ERROR:
+			{
+                return "ERROR";
+            }
+
+            case LogEventLevel.WARN:
+			{
+                return "WARN";
+            }
+
+            case LogEventLevel.FATAL:
+			{
+                return "FATAL";
+            }
+
+            case LogEventLevel.ALL:
+			{
+                return "ALL";
+            }
+		}
+
+		return "UNKNOWN";
+    }
+
+    public function LogEvent(message:String = "",
+							 level:int = 31 /* LogEventLevel.ALL */)
+    {
+        super(LogEvent.eventID, false, false);
+
+        this.message = message;
+        this.level = level;
+    }
+
+    public var level:int;
+
+    public var message:String;
+
+    override public function clone():Event
+    {
+        return new LogEvent(message, /*type,*/ level);
+    }
+}
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
new file mode 100644
index 0000000..a12098b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging
+{
+	import flash.errors.IllegalOperationError;
+public final class LogEventLevel
+{
+	    public static const FATAL:int = 16;
+	
+	    public static const ERROR:int = 8;
+	    
+	    public static const WARN:int = 4;
+	    
+	    public static const INFO:int = 2;
+	    
+	    public static const DEBUG:int = 1;
+	    
+	    public static const ALL:int = (DEBUG | INFO | WARN | ERROR | FATAL);
+	
+	    public static const NONE:int = 0;
+	    
+	    public static const LoggerLevelList:Array = [DEBUG, INFO, WARN, ERROR, FATAL, ALL];
+    
+		public static function isValidLevel(level:int) :Boolean {
+			for ( var i:int = 0; i < LoggerLevelList.length ; ++i ) {
+				if ( (LoggerLevelList[i] == level) )
+					return true;
+			}
+			return false;
+		}
+		
+		public static function isValidMask(mask:int ):Boolean {
+			var allMask:int = 0;
+			for ( var i:int = 0; i< LoggerLevelList.length; ++i ) {
+				allMask = (allMask | (LoggerLevelList[i]));
+			}
+			if ( (allMask | mask ) == allMask ) return true;
+			return false;
+		}
+		
+		public static function getUpperMask(level:int ) :int {
+			var result:int = 0;
+			if ( !isValidLevel(level) ) {
+				throw new IllegalOperationError("Please input an valid level for getUpperMask.");
+			} 
+			if ( level == ALL) return level;
+			for ( var i:int =0; i< LoggerLevelList.length; ++i ) {
+				if ( (LoggerLevelList[i] >= level) && (LoggerLevelList[i] < ALL) ) {
+					result =result | LoggerLevelList[i];
+				}
+			}
+			return result;
+		}
+
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
new file mode 100644
index 0000000..b5a23be
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+package com.adobe.linguistics.spelling.core.logging
+{
+	import flash.errors.IllegalOperationError;
+	import flash.events.EventDispatcher;
+public class LogLogger extends EventDispatcher implements ILogger
+{
+	public function LogLogger(category:String)
+	{
+		super();
+
+		_category = category;
+	}
+
+	/**
+	 *  @private
+	 *  Storage for the category property.
+	 */
+	private var _category:String;
+
+	/**
+	 *  The category this logger send messages for.
+	 *  
+	 */	
+	public function get category():String
+	{
+		return _category;
+	}
+	
+	public function log(level:int, msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( level, msg, rest);
+	}
+
+	public function debug(msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( LogEventLevel.DEBUG, msg, rest);
+	}
+
+	public function error(msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( LogEventLevel.ERROR, msg, rest);
+	}
+
+	public function fatal(msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( LogEventLevel.FATAL, msg, rest);
+	}
+
+	public function info(msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( LogEventLevel.INFO, msg, rest);
+	}
+
+	public function warn(msg:String, ... rest):void
+	{
+		dispatchLoggerEvent( LogEventLevel.WARN, msg, rest);
+	}
+	
+	private function dispatchLoggerEvent(level:int, msg:String, options:Array):void {
+		// we don't want to allow people to log messages at the 
+		// Log.Level.ALL level, so throw a RTE if they do
+		if ( !LogEventLevel.isValidLevel( level ) )
+		{
+			throw new IllegalOperationError("Please check for level permit.");
+		}
+        	
+		if (hasEventListener(LogEvent.eventID))
+		{
+			// replace all of the parameters in the msg string
+			for (var i:int = 0; i < options.length; i++)
+			{
+				msg = msg.replace(new RegExp("\\{"+i+"\\}", "g"), options[i]);
+			}
+
+			dispatchEvent(new LogEvent(msg, level));
+		}
+		
+	}
+	
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
new file mode 100644
index 0000000..61a5a4a
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging.targets
+{
+	public class ArrayTarget extends CollectionTarget
+	{
+		public var items:Array;
+		public function ArrayTarget(arr:Array, usingLevelMaskMode:Boolean = false)
+		{
+			this.items = arr;
+			super(usingLevelMaskMode);
+		}
+		public override function internalLog(msg:String,lvl:int):void {
+			items.push( {date:this.date, time:this.time, category:this.category, levelString:this.levelString, message:msg, level:lvl } );
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
new file mode 100644
index 0000000..b355f04
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging.targets
+{
+	import com.adobe.linguistics.spelling.core.logging.*;
+	public class CollectionTarget extends AbstractTarget
+	{
+	    public var fieldSeparator:String = " ";
+	
+	    public var includeCategory:Boolean;
+	
+	    public var includeDate:Boolean;
+	
+	    public var includeLevel:Boolean;
+	
+	    public var includeTime:Boolean;
+
+	    protected var date:String = "";
+	    protected var time:String = "";
+	    protected var levelString:String = "";
+	    protected var category:String = "";
+		
+		public function CollectionTarget(usingLevelMaskMode:Boolean = false)
+		{
+	        super(usingLevelMaskMode);
+	        includeTime = false;
+	        includeDate = false;
+	        includeCategory = false;
+	        includeLevel = false;
+		}
+
+	    override public function logEvent(event:LogEvent):void
+	    {
+	    	date = "";
+	    	time = "";
+	    	levelString = "";
+	    	category = "";
+	        if (includeDate || includeTime)
+	        {
+	            var d:Date = new Date();
+	            if (includeDate)
+	            {
+	                date = Number(d.getMonth() + 1).toString() + "/" +
+	                       d.getDate().toString() + "/" + 
+	                       d.getFullYear();
+	            }   
+	            if (includeTime)
+	            {
+	                time += padTime(d.getHours()) + ":" +
+	                        padTime(d.getMinutes()) + ":" +
+	                        padTime(d.getSeconds()) + "." +
+	                        padTime(d.getMilliseconds(), true);
+	            }
+	        }
+	        
+	        if (includeLevel)
+	        {
+	            levelString = LogEvent.getLevelString(event.level);
+	        }
+	
+	        category = includeCategory ? ILogger(event.target).category:"";
+	
+	        internalLog(event.message,event.level);
+	    }
+	    
+	    private function padTime(num:Number, millis:Boolean = false):String
+	    {
+	        if (millis)
+	        {
+	            if (num < 10)
+	                return "00" + num.toString();
+	            else if (num < 100)
+	                return "0" + num.toString();
+	            else 
+	                return num.toString();
+	        }
+	        else
+	        {
+	            return num > 9 ? num.toString() : "0" + num.toString();
+	        }
+	    }
+	
+	    public function internalLog(message:String, level:int):void
+	    {
+	        // override this method to perform the redirection to the desired output
+	    }
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
new file mode 100644
index 0000000..c1b66eb
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
@@ -0,0 +1,104 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging.targets
+{
+	import com.adobe.linguistics.spelling.core.logging.*;
+public class LineFormattedTarget extends AbstractTarget
+{
+    public function LineFormattedTarget(usingLevelMaskMode:Boolean = false)
+    {
+        super(usingLevelMaskMode);
+
+        includeTime = false;
+        includeDate = false;
+        includeCategory = false;
+        includeLevel = false;
+    }
+
+    public var fieldSeparator:String = " ";
+
+    public var includeCategory:Boolean;
+
+    public var includeDate:Boolean;
+
+    public var includeLevel:Boolean;
+
+    public var includeTime:Boolean;
+
+    override public function logEvent(event:LogEvent):void
+    {
+        var date:String = ""
+        if (includeDate || includeTime)
+        {
+            var d:Date = new Date();
+            if (includeDate)
+            {
+                date = Number(d.getMonth() + 1).toString() + "/" +
+                       d.getDate().toString() + "/" + 
+                       d.getFullYear() + fieldSeparator;
+            }   
+            if (includeTime)
+            {
+                date += padTime(d.getHours()) + ":" +
+                        padTime(d.getMinutes()) + ":" +
+                        padTime(d.getSeconds()) + "." +
+                        padTime(d.getMilliseconds(), true) + fieldSeparator;
+            }
+        }
+        
+        var level:String = "";
+        if (includeLevel)
+        {
+            level = "[" + LogEvent.getLevelString(event.level) +
+                    "]" + fieldSeparator;
+        }
+
+        var category:String = includeCategory ?
+                              ILogger(event.target).category + fieldSeparator :
+                              "";
+
+        internalLog(date + category+ level  + event.message,event.level);
+    }
+    
+    private function padTime(num:Number, millis:Boolean = false):String
+    {
+        if (millis)
+        {
+            if (num < 10)
+                return "00" + num.toString();
+            else if (num < 100)
+                return "0" + num.toString();
+            else 
+                return num.toString();
+        }
+        else
+        {
+            return num > 9 ? num.toString() : "0" + num.toString();
+        }
+    }
+
+    public function internalLog(message:String, level:int):void
+    {
+        // override this method to perform the redirection to the desired output
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
new file mode 100644
index 0000000..bb4d75b
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging.targets
+{
+    
+    import flash.text.TextField;
+    public class TextFieldTarget extends LineFormattedTarget 
+    {
+        public var autoScroll:Boolean = true ;
+        public var textfield:TextField ;
+
+        public function TextFieldTarget( textfield:TextField,usingLevelMaskMode:Boolean = false )
+        {
+            super(usingLevelMaskMode);
+            this.textfield = textfield ;
+        }
+        
+        public override function internalLog( message:String , level:int ):void
+        {
+            if ( textfield != null )
+            {
+				textfield.appendText( message + "\r");
+                if ( autoScroll )
+                {
+                    textfield.scrollV  = textfield.maxScrollV ;
+                }
+            }
+            else
+            {
+                throw new ReferenceError( "The internal textfield reference of the target not must be null." ) ;
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
new file mode 100644
index 0000000..5571fcd
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.logging.targets
+{
+
+public class TraceTarget extends LineFormattedTarget
+{
+    public function TraceTarget(usingLevelMaskMode:Boolean = false)
+    {
+        super(usingLevelMaskMode);
+    }
+
+    public override function internalLog(message:String,level:int):void
+    {
+        trace(message);
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
new file mode 100644
index 0000000..4ec678d
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
@@ -0,0 +1,137 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	import com.adobe.linguistics.spelling.core.LinguisticRule;
+	
+	public class AffixEntry
+	{
+		private var _flag:int;
+		private var _stripValue:String; /*stripping characters from beginning (at prefix rules) or end (at suffix rules) of the word  */
+		private var _affixValue:String; /* affix (optionally with flags of continuation classes, separated by a slash)  */
+		private var _conditionString:String; /*Zero stripping or affix are indicated by zero. 
+		Zero condition is indicated by dot. Condition is a simplified, regular expression-like pattern, 
+		which must be met before the affix can be applied. (Dot signs an arbitrary character. Characters 
+		in braces sign an arbitrary character from the character subset. Dash hasn’t got special meaning, 
+		but circumflex (^) next the first brace sets the complementer character set.)  */
+		private var _conditionPattern:RegExp;
+		private var _permissionToCombine:Boolean; /* Cross product (permission to combine prefixes and suffixes). Possible values: Y (yes) or N (no) */
+		private var _type:int; // 0 means prefix, 1 means suffix...
+		private var _morphologicalFields:String; //Optional morphological fields separated by spaces or tabulators. 
+		private var _contclass:String; //Added for Double affix support
+		
+		private var _attrMgr:LinguisticRule;		
+
+		
+		public function AffixEntry(affixFlag:int, stripString:String, affixValue:String, conditionStr:String, morph:String = "", permission:Boolean = false, affixType:int = 0, contclass:String=null)
+		{
+			this.flag = affixFlag;
+			this.conditionString = conditionStr;
+			this.stripValue = stripString;
+			this.affixKey = affixValue;
+			this.permissionToCombine = permission;
+			this.type = affixType;
+			this.morphologicalFields = morph;
+			this.attributeManager = null;
+			this.contclass=contclass;//can be null too
+			this._conditionPattern = (affixType == 0) ? new RegExp("^"+conditionStr+".*"+"$"): new RegExp("^"+".*"+conditionStr+"$");
+		}
+		
+		public function set attributeManager( attrMgr:LinguisticRule):void {
+			this._attrMgr = attrMgr;
+		}
+		
+		public function get attributeManager( ):LinguisticRule {
+			return this._attrMgr;
+		}
+		
+		public function set morphologicalFields(value:String):void {
+			this._morphologicalFields = value;
+		}
+		
+		public function get morphologicalFields():String {
+			return this._morphologicalFields;
+		}
+		
+		public function set permissionToCombine(value:Boolean) : void {
+			this._permissionToCombine = value;
+		}
+		
+		public function get permissionToCombine():Boolean {
+			return this._permissionToCombine;
+		}
+		
+		public function get flag():int {
+			return this._flag;
+		}
+		public function set flag(affixFlag:int):void {
+			this._flag = affixFlag;
+		}
+		
+		public function get type():int {
+			return this._type;
+		}
+		
+		public function set type(affixType:int):void {
+			this._type = affixType;
+		}
+		
+		public function set stripValue(value:String):void {
+			this._stripValue = value;
+		} 
+		
+		public function get stripValue():String {
+			return this._stripValue;
+		}
+		
+		public function set affixKey(value:String):void {
+			this._affixValue = value;
+		}
+		
+		public function get affixKey():String {
+			return this._affixValue;
+		}
+		
+		public function set contclass(value:String):void {
+			this._contclass = value;
+		}
+		
+		public function get contclass():String {
+			return this._contclass;
+		}
+		
+		public function get conditionString():String {
+			return this._conditionString;
+		}
+		
+		public function set conditionString(value:String):void {
+			this._conditionString  = value;
+		}
+		
+		public function get conditionPattern():RegExp {
+			return this._conditionPattern;
+		}
+		public function set conditionPattern(value:RegExp):void {
+			this._conditionPattern = value;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
new file mode 100644
index 0000000..2633bd6
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	
+	public class AffixRule
+	{
+		private var _name:String;
+		private var _type:uint;
+		private var _stripValue:String;
+		private var _affixValue:String;
+		private var _conditionPattern:String;
+		private var _permissionToCombine:Boolean;
+		
+		public function AffixRule(affixName:String, affixType:uint, stripString:String, affixString:String, conditionString:String, permission:Boolean = true)
+		{
+			this.name = affixName;
+			this._conditionPattern = conditionString;
+			this.type = affixType;
+			this.stripValue = stripString;
+			this.affixValue = affixString;
+			this.permissionToCombine = permission;
+			
+		}
+		
+		public function set permissionToCombine(value:Boolean) : void {
+			this._permissionToCombine = value;
+		}
+		
+		public function get permissionToCombine():Boolean {
+			return this._permissionToCombine;
+		}
+		
+		public function get name():String {
+			return this._name;
+		}
+		public function set name(affixName:String):void {
+			this._name = affixName;
+		}
+		
+		public function get type():uint {
+			return this._type;
+		}
+		
+		public function set type(affixType:uint):void {
+			this._type = affixType;
+		}
+		
+		public function set stripValue(value:String):void {
+			this._stripValue = value;
+		} 
+		
+		public function get stripValue():String {
+			return this._stripValue;
+		}
+		
+		public function set affixValue(value:String):void {
+			this._affixValue = value;
+		}
+		
+		public function get affixValue():String {
+			return this._affixValue;
+		}
+		
+		public function get conditionPattern():String {
+			return this._conditionPattern;
+		}
+		
+		public function set conditionPattern(value:String):void {
+			this._conditionPattern  = value;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as
new file mode 100644
index 0000000..3c241ed
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as
@@ -0,0 +1,39 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	
+	public class MapFilter
+	{
+		private var _mapCharSet:String;
+		public function MapFilter(mapString:String)
+		{
+			this.mapCharSet = mapString;
+		}
+		public function get mapCharSet():String {
+			return this._mapCharSet;
+		}
+		public function set mapCharSet(value:String) : void {
+			this._mapCharSet = value;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
new file mode 100644
index 0000000..b448338
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
@@ -0,0 +1,245 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	import com.adobe.linguistics.spelling.core.HashEntry;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	public class OptimizedPrefixEntry extends AffixEntry
+	{
+		private var _flagNext:OptimizedPrefixEntry;
+		private var _keyNext:OptimizedPrefixEntry;
+		private var _flags:Array;
+		private var _pfxTable:Array;
+		public function OptimizedPrefixEntry(pfxEntry:PrefixEntry)
+		{
+			
+			super(pfxEntry.flag,pfxEntry.stripValue,pfxEntry.affixKey,pfxEntry.conditionString,pfxEntry.morphologicalFields, pfxEntry.permissionToCombine, 0,pfxEntry.contclass);
+			_flags = new Array();
+			this._pfxTable = new Array();
+			this.nextElementWithFlag = null;
+			this.nextElementWithKey = null;
+			_flags.push(this.flag);
+			this._pfxTable.push(pfxEntry);
+			this.flag = -1;
+			this.conditionString = "";
+		}
+
+		public function isSimilarObject(pfxEntry:PrefixEntry):Boolean {
+			var chkString:String=this.contclass+pfxEntry.contclass;
+			if(chkString)chkString=chkString.split('').sort().join('').replace(/(.)\1+/gi,'$1');//this pattern removes any repetition from strings. this will work only because we are converting n' or q' to Long numbers in decode flags
+			if ( (this.stripValue == pfxEntry.stripValue) && (this.affixKey == pfxEntry.affixKey) && (this.permissionToCombine == pfxEntry.permissionToCombine) && (this.morphologicalFields == pfxEntry.morphologicalFields)&&(this.contclass==chkString) )	return true;
+			return false;
+		} 
+		
+		public function extendObject( pfxEntry:PrefixEntry ):Boolean {
+			if ( !isSimilarObject(pfxEntry) )	{
+				return false;
+			}
+			_flags.push( pfxEntry.flag);
+			this._pfxTable.push( pfxEntry );
+		
+			var newConditionString:String;
+			newConditionString = this.conditionPattern.source + "|" + "^"+pfxEntry.conditionString+".*"+"$";
+			this.conditionPattern  = new RegExp ( newConditionString);
+			this.contclass=pfxEntry.contclass;
+			return true;
+		}
+
+		public function get nextElementWithKey():OptimizedPrefixEntry {
+			return this._keyNext;
+		}
+		
+		public function set nextElementWithKey(pfxEntry:OptimizedPrefixEntry):void {
+			this._keyNext = pfxEntry;
+		}
+		
+		public function get nextElementWithFlag():OptimizedPrefixEntry {
+			return this._flagNext;
+		}
+		
+		public function set nextElementWithFlag(pfxEntry:OptimizedPrefixEntry):void {
+			this._flagNext = pfxEntry;
+		}
+		
+		public function get flags():Array {
+			return this._flags;
+		}
+
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		// check if this prefix entry matches
+		public function checkWord( word:String, sfxopts:int, ppfx:AffixEntry, inCompound:int, needFlag:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+			// if this suffix is being cross checked with a prefix
+			// but it does not support cross products skip it
+			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;
+			// on entry prefix is 0 length or already matches the beginning of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip) ) {
+				// generate new root word by removing prefix and adding
+				// back any characters that would have been stripped
+				word = this.stripValue + word.substr(this.affixKey.length);
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if ( he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+								return he;
+							}
+							he = he.next;
+						}
+					}
+				} 
+				
+			}
+			return he;
+		}
+
+		// check if this prefix entry matches
+		public function checkWord2( word:String, inCompound:int, needFlag:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int,j:int;
+			// on entry prefix is 0 length or already matches the beginning of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip) ) {
+				// generate new root word by removing prefix and adding
+				// back any characters that would have been stripped
+				word = this.stripValue + word.substr(this.affixKey.length);
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if ( he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+								for ( j=0;j<this._pfxTable.length;++j) {
+									if ( (this._pfxTable[j] ).conditionPattern.test(word) ) {
+										if ( he.testAffix(this._flags[j]) ){
+											return he;
+										}
+									}
+								}
+							}
+							he = he.next;
+						}
+					}
+					//if ((opts & aeXPRODUCT) && in_compound)
+					if ( this.permissionToCombine ) {
+						for(i=0; j<this.flags[i];i++)
+						{
+							he = this.attributeManager.optSuffixCheck2(word, InternalConstants.aeXPRODUCT,this, needFlag, inCompound,this.flags[i]);
+							
+							if (he) 
+							{
+							
+								for ( j=0;j<this._pfxTable.length;++j) 
+								{
+									if ( (this._pfxTable[j] ).conditionPattern.test(word) && (this._pfxTable[j].flag ==this.flags[i]) )
+									{
+										
+											return he;
+										
+									}
+								}
+							he = null;	
+							} 
+						}
+					}
+				} 
+				
+			}
+			return he;
+		}
+		 
+		//checkTwoWord
+		public function checkTwoWord( word:String, inCompound:int, needFlag:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int,j:int;
+			// on entry prefix is 0 length or already matches the beginning of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip) ) {
+				// generate new root word by removing prefix and adding
+				// back any characters that would have been stripped
+				word = this.stripValue + word.substr(this.affixKey.length);
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// do not look word in hash table
+					
+					//if ((opts & aeXPRODUCT) && in_compound)
+					if ( this.permissionToCombine && inCompound!=1/*IN_CPD_BEGIN*/) {//TODO: figure this constant
+						for(i=0; j<this.flags[i];i++)
+						{
+						
+							he = this.attributeManager.optTwoSuffixCheck(word, InternalConstants.aeXPRODUCT,this,needFlag,this.flags[i]);//this is the c2
+							if (he) {
+								for ( j=0;j<this._pfxTable.length;++j) { //Squiggly will handle undrinkables from here
+									if ( (this._pfxTable[j] ).conditionPattern.test(word)&& (this._pfxTable[j].flag ==this.flags[i]) ) 
+									{
+									
+											return he;
+										
+									}
+								}
+								he = null;
+							}
+						}
+					}
+				} 
+				
+			}
+			return he;
+		}
+		//--
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
new file mode 100644
index 0000000..7d6ee58
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
@@ -0,0 +1,301 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	import com.adobe.linguistics.spelling.core.HashEntry;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	import com.adobe.linguistics.spelling.core.utils.StringUtils;
+	
+	public class OptimizedSuffixEntry  extends AffixEntry
+	{
+		private var _flagNext:OptimizedSuffixEntry;
+		private var _keyNext:OptimizedSuffixEntry;
+		private var _flags:Array;
+		private var _sfxTable:Array;
+		private var _reverseAffixKey:String;
+		public function OptimizedSuffixEntry(sfxEntry:SuffixEntry)
+		{
+			super(sfxEntry.flag,sfxEntry.stripValue,sfxEntry.affixKey,sfxEntry.conditionString,sfxEntry.morphologicalFields, sfxEntry.permissionToCombine, sfxEntry.type,sfxEntry.contclass);
+			_flags = new Array();
+			_sfxTable = new Array();
+			this.nextElementWithFlag = null;
+			this.nextElementWithKey = null;
+			_flags.push(this.flag);
+			_sfxTable.push(sfxEntry);
+			this.reverseAffixKey = StringUtils.reverseString(this.affixKey);
+			this.flag = -1;
+			this.conditionString = "";
+		}
+		
+		public function isSimilarObject(sfxEntry:SuffixEntry):Boolean {
+			var chkString:String=this.contclass+sfxEntry.contclass;
+			if(chkString)chkString=chkString.split('').sort().join('').replace(/(.)\1+/gi,'$1');//this pattern removes any repetition from strings. this will work only because we are converting n' or q' to Long numbers in decode flags
+			if ( (this.stripValue == sfxEntry.stripValue) && (this.affixKey == sfxEntry.affixKey) && (this.permissionToCombine == sfxEntry.permissionToCombine) && (this.morphologicalFields == sfxEntry.morphologicalFields) &&(this.contclass==chkString) )	return true;
+			return false;
+		} 
+		
+		public function extendObject( sfxEntry:SuffixEntry ):Boolean {
+			
+			 if ( !isSimilarObject(sfxEntry) ) return false;
+			_flags.push(sfxEntry.flag);
+			_sfxTable.push(sfxEntry);
+			var newConditionString:String;
+			newConditionString = this.conditionPattern.source + "|" + "^"+".*"+sfxEntry.conditionString+"$";
+			this.conditionPattern  = new RegExp ( newConditionString);
+			//now add in contclass
+			this.contclass=sfxEntry.contclass;
+			return true;
+		}
+		
+		public function set reverseAffixKey(value:String):void {
+			this._reverseAffixKey = value;
+		}
+		
+		public function get reverseAffixKey():String {
+			return this._reverseAffixKey;
+		}
+		
+		public function get nextElementWithKey():OptimizedSuffixEntry {
+			return this._keyNext;
+		}
+		
+		public function set nextElementWithKey(pfxEntry:OptimizedSuffixEntry):void {
+			this._keyNext = pfxEntry;
+		}
+		
+		public function get nextElementWithFlag():OptimizedSuffixEntry {
+			return this._flagNext;
+		}
+		
+		public function set nextElementWithFlag(pfxEntry:OptimizedSuffixEntry):void {
+			this._flagNext = pfxEntry;
+		}
+		
+		public function get flags():Array {
+			return this._flags;
+		}
+		
+		/*
+		 * Deprecated function for now...
+		 * History: 
+		 *          A pre-version of implementation for error detection. After I optimized the code for performance,
+		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
+		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
+		 */
+		// see if this suffix is present in the word
+		public function checkWord( word:String, needFlag:int, inCompound:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+
+			// upon entry suffix is 0 length or already matches the end of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
+				// generate new root word by removing suffix and adding
+				// back any characters that would have been stripped or
+				// or null terminating the shorter string
+				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if ( he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+								return he;
+							}
+							he = he.next;
+						}
+					}
+					//if ((opts & aeXPRODUCT) && in_compound)
+					if ( this.permissionToCombine ) {
+						he = this.attributeManager.optPrefixCheck(word, InternalConstants.aeXPRODUCT,this, needFlag, inCompound);
+						if (he) return he; 
+					}
+				} 
+				
+			}
+			return he;
+		}
+		
+		//for develepors only, function used for printing flags when flag_mode=FLAG.LONG presently not being called anywhere
+		public function printFlag(flag:Number):void{
+			var result:String =  String.fromCharCode(flag>>8) + String.fromCharCode(flag-((flag>>8)<<8));
+			var x:String= this.affixKey;
+		}
+		// see if this suffix is present in the word
+		public function checkWord2( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int, cclass:int, pfxcclass:int=0):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+
+			// if this suffix is being cross checked with a prefix
+			// but it does not support cross products skip it
+			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;
+
+			// upon entry suffix is 0 length or already matches the end of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
+				// generate new root word by removing suffix and adding
+				// back any characters that would have been stripped or
+				// or null terminating the shorter string
+				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if (  (( he.testAffixs(this._flags) ) && ( (!needFlag) || he.testAffix(needFlag) ))||(ppfx && ppfx.contclass) ) {
+								for ( var j:int=0;j<this._sfxTable.length;++j) {
+									if ( (this._sfxTable[j] ).conditionPattern.test(word) ) {
+										if(!ppfx)
+										{
+											if(cclass)
+											{
+												if (he.testAffix(this._flags[j]) && HashEntry.TESTAFF(this.contclass,cclass) )//should handle cases like drink->able->s also in un-run-able-s if run-->able and able-->s and s-->un this should suffice
+													return he;
+											}
+											else											
+											{	if(he.testAffix(this._flags[j]))//should handle all normal cases like drink->able or drink->s
+												return he;
+											}
+											
+																						
+										}
+										else
+										{
+											if(this.contclass && he.testAffix(this._flags[j]) && HashEntry.TESTAFF(this.contclass,cclass) && !pfxcclass) // handle when suffix has contclass like l'->autre->s
+											{
+											return he;
+											}
+											if(ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) && he.testAffix(cclass) && !pfxcclass) //handle when prefix has contclass like milli->litre->s
+											{
+												return he;	
+											}
+											if(he.testAffix(this._flags[j]) && he.testAffix(cclass))//handle normal cases when both pfx and sfx exist in hash affix string
+											{
+											return he;
+											}
+											
+											//special case of un-drink-able-s
+											if(    (he.testAffix(pfxcclass) && ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) && this.contclass && HashEntry.TESTAFF(this.contclass,cclass)) 
+											   ||  (he.testAffix(this._flags[j]) && this.contclass && HashEntry.TESTAFF(this.contclass,cclass) && HashEntry.TESTAFF(this.contclass,pfxcclass))
+											   )
+											{
+												return he;
+											}
+											
+																						
+										}
+											
+										}
+								}
+							}
+							he = he.next;
+						}
+					}
+
+				} 
+				
+			}
+			return he;
+		}
+		
+		// Function for two level suffix checkword
+		// see if this suffix is present in the word
+		public function checkTwoWord( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, cclass:int, pfxcclass:int=0):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+			
+			// if this suffix is being cross checked with a prefix
+			// but it does not support cross products skip it
+			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;
+			
+			// upon entry suffix is 0 length or already matches the end of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
+				// generate new root word by removing suffix and adding
+				// back any characters that would have been stripped or
+				// or null terminating the shorter string
+				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then see if for conditional suffix and if this has been stripped by a possible
+				// contclass check the remaining word 
+				// eg: if drinkables was original word and after possible stripping of s we have drinkable very if 
+				// now check drinkable, able will be stripped and drink will be found that hash entry will then be returned
+				if ( this.conditionPattern.test( word ) ) {//checks a whole group of 
+					
+					if(ppfx)
+					{ //check for conditional suffix
+						if( contclass!=null && HashEntry.TESTAFF(contclass, pfxcclass))
+						{
+							he = this.attributeManager.optSuffixCheck2(word, 0, null,needFlag,0,cclass,pfxcclass);//we are not sending ppfx here as it will not be needed.
+						}
+						else
+						{
+							he = this.attributeManager.optSuffixCheck2(word, sfxopts, ppfx,needFlag,0,cclass,pfxcclass);
+						}
+					}
+					else
+					{
+						he = this.attributeManager.optSuffixCheck2(word, 0, null,needFlag,0,cclass,0);
+					}
+					if (he) {
+						for ( var j:int=0;j<this._sfxTable.length;++j) { //Squiggly will handle drink->able->s from here
+							if ( (this._sfxTable[j]).conditionPattern.test(word) && cclass==(this._sfxTable[j]).flag) {//only permit words which end with s in drinkables
+								
+									return he;
+							
+							}
+						}
+						he = null;
+					}
+					
+				} 
+				
+			}
+			
+			return he;
+		}
+		//--
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
new file mode 100644
index 0000000..7df2e55
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+package com.adobe.linguistics.spelling.core.rule
+{
+	import com.adobe.linguistics.spelling.core.HashEntry;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+	public class PrefixEntry extends AffixEntry
+	{
+		private var _flagNext:PrefixEntry;
+		private var _keyNext:PrefixEntry;
+		public function PrefixEntry(affixFlag:int, stripString:String, affixValue:String, conditionString:String, morph:String = "", permission:Boolean = false,contclass:String=null)
+		{
+			super(affixFlag,stripString,affixValue,conditionString,morph, permission, 0,contclass);
+			this.nextElementWithFlag = null;
+			this.nextElementWithKey = null;
+		}
+		
+		public function add(root:String):String {
+			if ( this.conditionPattern.test(root) )
+				return this.affixKey + root.substring(this.stripValue.length );
+			return null; 
+		}
+		
+		public function get nextElementWithKey():PrefixEntry {
+			return this._keyNext;
+		}
+		
+		public function set nextElementWithKey(pfxEntry:PrefixEntry):void {
+			this._keyNext = pfxEntry;
+		}
+		
+		public function get nextElementWithFlag():PrefixEntry {
+			return this._flagNext;
+		}
+		
+		public function set nextElementWithFlag(pfxEntry:PrefixEntry):void {
+			this._flagNext = pfxEntry;
+		}
+		
+		// check if this prefix entry matches
+		public function checkWord( word:String, inCompound:int, needFlag:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+			// on entry prefix is 0 length or already matches the beginning of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip) ) {
+				// generate new root word by removing prefix and adding
+				// back any characters that would have been stripped
+				word = this.stripValue + word.substr(this.affixKey.length);
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if ( he.testAffix(this.flag) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+								return he;
+							}
+							he = he.next;
+						}
+					}
+					//if ((opts & aeXPRODUCT) && in_compound)
+					if ( this.permissionToCombine ) {
+						he = this.attributeManager.suffixCheck2(word, InternalConstants.aeXPRODUCT,this, needFlag, inCompound);
+						if (he) return he; 
+					}
+				} 
+				
+			}
+			return he;
+		}
+
+
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
new file mode 100644
index 0000000..8f0b1d9
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+
+package com.adobe.linguistics.spelling.core.rule
+{
+		/*
+		 * Deprecated class for now...
+		 * ToDo: It is a place holder for metaphone algorithm in the rule based engine.
+		 */
+	public class ReplacementFilter
+	{
+		public function ReplacementFilter()
+		{
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
new file mode 100644
index 0000000..4763059
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
@@ -0,0 +1,48 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.rule
+{
+	public class SimpleFilter
+	{
+		private var _matchString:String;
+		private var _replacementString:String;
+		public function SimpleFilter(matchingString:String, replacementString:String)
+		{
+			this.matchString = matchingString;
+			this.replacement = replacementString;
+		}
+		
+		public function set matchString(value:String) :void {
+			this._matchString = value;
+		}
+		public function get matchString():String {
+			return this._matchString;
+		}
+		
+		public function set replacement(value:String) :void {
+			this._replacementString = value;
+		}
+		public function get replacement() :String {
+			return this._replacementString;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as
new file mode 100644
index 0000000..313ada3
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.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.core.rule
+{
+	import com.adobe.linguistics.spelling.core.HashEntry;
+	import com.adobe.linguistics.spelling.core.env.InternalConstants;
+
+	public class SuffixEntry extends AffixEntry
+	{
+		private var _flagNext:SuffixEntry;
+		private var _keyNext:SuffixEntry;
+		private var _conditionPattern2:RegExp = null;;
+		private var _noTestFlag:Boolean = false;
+		public function SuffixEntry(affixFlag:int, stripString:String, affixValue:String, conditionString:String, morph:String = "", permission:Boolean = false, contclass:String=null)
+		{
+			super(affixFlag,stripString,affixValue,conditionString,morph, permission, 1,contclass);
+			this.nextElementWithFlag = null;
+			this.nextElementWithKey = null;
+			if ( this.stripValue != "" ) {
+				if ( this.conditionString == "." ) {
+						this._conditionPattern2 = null;
+						this._noTestFlag = true;
+					
+				}else {
+					var stripPattern:RegExp = new RegExp ( "^(.*)"+this.stripValue+"$" );
+					var strArr:Array;
+					if ( (strArr = this.conditionString.match(stripPattern) ) != null ) {
+						if ( strArr[1] != "" ) {
+							this._conditionPattern2 = new RegExp( "^.*" + strArr[1] + "$" );
+						}else {
+							this._conditionPattern2 = null;
+							this._noTestFlag = true;
+						}
+					}else {
+						this._conditionPattern2 = this.conditionPattern;
+					}
+				}
+			}
+			
+		}
+		
+		public function add(root:String):String {
+			if ( this.conditionPattern.test(root) )
+				return root.substring(0, (root.length-this.stripValue.length) ) + this.affixKey;
+			return null; 
+		}
+		
+		public function get nextElementWithKey():SuffixEntry {
+			return this._keyNext;
+		}
+		
+		public function set nextElementWithKey(pfxEntry:SuffixEntry):void {
+			this._keyNext = pfxEntry;
+		}
+		
+		public function get nextElementWithFlag():SuffixEntry {
+			return this._flagNext;
+		}
+		
+		public function set nextElementWithFlag(pfxEntry:SuffixEntry):void {
+			this._flagNext = pfxEntry;
+		}
+
+		// see if this suffix is present in the word
+		public function checkWord( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int):HashEntry {
+			var disLen:int = word.length - this.affixKey.length;
+			var he:HashEntry = null;
+			var i:int;
+
+			// if this suffix is being cross checked with a prefix
+			// but it does not support cross products skip it
+			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;
+
+			// upon entry suffix is 0 length or already matches the end of the word.
+			// So if the remaining root word has positive length
+			// and if there are enough chars in root word and added back strip chars
+			// to meet the number of characters conditions, then test it
+			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
+				// generate new root word by removing suffix and adding
+				// back any characters that would have been stripped or
+				// or null terminating the shorter string
+				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
+				// now make sure all of the conditions on characters
+				// are met.  Please see the appendix at the end of
+				// this file for more info on exactly what is being
+				// tested
+				// if all conditions are met then check if resulting
+				// root word in the dictionary
+				if ( this._noTestFlag || this.conditionPattern.test( word ) ) {
+					// look word in hash table
+					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+						while( he ) {
+							if ( he.testAffix(this.flag) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+								return he;
+							}
+							he = he.next;
+						}
+					}
+
+				} 
+				
+			}
+			return he;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
new file mode 100644
index 0000000..1092179
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
@@ -0,0 +1,94 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core.utils
+{
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IOErrorEvent;
+	import flash.events.SecurityErrorEvent;
+	import flash.net.URLLoader;
+	import flash.net.URLLoaderDataFormat;
+	import flash.net.URLRequest;
+	import flash.utils.ByteArray;
+	import flash.utils.getTimer;
+	
+	public class DictionaryLoader extends EventDispatcher
+	{
+		private var dataloader:URLLoader;
+		private var _data:ByteArray;
+		public function DictionaryLoader(request:URLRequest=null)
+		{
+			dataloader = new URLLoader();
+			dataloader.dataFormat = URLLoaderDataFormat.BINARY;
+			dataloader.addEventListener(Event.COMPLETE,handleComplete);
+			dataloader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+			dataloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+			if (request) { 
+				try {
+					load(request); 
+				}
+				catch (error:Error) {
+									
+				}
+			}
+			else 
+			{
+				dispatchEvent(new Event(Event.COMPLETE));
+			}
+		}
+		
+		public function get bytesTotal():uint {
+			return dataloader.bytesTotal;
+		}
+		
+		public function get data():ByteArray {
+			return this._data;
+		}
+
+		public function load(request:URLRequest):void {
+			_data = null;
+			//trace("Before Actual load: "+getTimer()+" "+dataloader.bytesLoaded);
+			dataloader.load(request);
+			
+		}
+
+		private function handleComplete(evt:Event):void {
+			// add to-do function.
+			this._data = (dataloader.data as ByteArray);
+			dispatchEvent(new Event(Event.COMPLETE));
+		}
+
+		private function handleError(evt:Event):void {
+			bounceEvent(evt);
+		}
+		
+		private function bounceEvent(evt:Event):void {
+			dispatchEvent(evt.clone());
+		}
+		
+		public function getData(): ByteArray {
+			return this._data;
+		}
+		
+
+	}
+}
\ No newline at end of file


[06/18] Squiggly spell checker donation from Adobe Systems Inc.

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

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

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

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

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

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

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as b/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
new file mode 100644
index 0000000..a8b826f
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IHighlighter.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+	import com.adobe.linguistics.utils.Token;
+	import __AS3__.vec.Vector;
+	import flash.geom.Point;
+	
+	public interface IHighlighter
+	{
+		function drawSquiggleAt(token:Token):void;
+		function clearSquiggles():void;
+		function set offsetPoint(op:Point):void;
+		function get offsetPoint():Point;
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as b/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
new file mode 100644
index 0000000..76c3c8e
--- /dev/null
+++ b/Squiggly/main/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/ui/IWordProcessor.as
@@ -0,0 +1,30 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework.ui
+{
+	import com.adobe.linguistics.utils.ITokenizer;
+	import com.adobe.linguistics.utils.Token;
+	
+	public interface IWordProcessor
+	{
+		function getWordAtPoint(x:uint, y:uint, externalTokenizer:ITokenizer=null):Token;
+		function replaceText(token:Token, replacement:String):void;
+	}
+}
\ No newline at end of file

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

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

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

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

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


[14/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditorPanel.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditorPanel.mxml b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditorPanel.mxml
new file mode 100644
index 0000000..6f4b613
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditorPanel.mxml
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+
+
+<!-- Demonstrate some example controls.  This example does not attempt to create a control for every property in the TextLayoutFramework -->
+
+<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
+		 height="570" label="Text Editor Example" backgroundColor="#FFFFFF"
+		 horizontalScrollPolicy="off" initialize="init()" verticalScrollPolicy="on">
+	<mx:Script>
+		<![CDATA[
+
+			import com.adobe.linguistics.spelling.SpellUIForTLF;
+			import com.adobe.linguistics.spelling.framework.SpellingService;
+			import com.adobe.linguistics.spelling.ui.IHighlighter;
+			import com.adobe.linguistics.spelling.ui.IWordProcessor;
+			import com.adobe.linguistics.utils.Token;
+			
+			import flash.display.Sprite;
+			import flash.system.Capabilities;
+			
+			import flashx.textLayout.container.ContainerController;
+			import flashx.textLayout.conversion.TextConverter;
+			import flashx.textLayout.edit.EditManager;
+			import flashx.textLayout.edit.ElementRange;
+			import flashx.textLayout.edit.IEditManager;
+			import flashx.textLayout.edit.SelectionState;
+			import flashx.textLayout.elements.Configuration;
+			import flashx.textLayout.elements.TextFlow;
+			import flashx.textLayout.events.SelectionEvent;
+			import flashx.textLayout.events.StatusChangeEvent;
+			import flashx.textLayout.formats.BlockProgression;
+			import flashx.textLayout.formats.Direction;
+			import flashx.textLayout.formats.ITextLayoutFormat;
+			import flashx.textLayout.formats.TextAlign;
+			import flashx.textLayout.formats.TextLayoutFormat;
+			import flashx.textLayout.formats.VerticalAlign;
+			import flashx.textLayout.tlf_internal;
+			import flashx.undo.UndoManager;
+			
+			// the textFlow being worked on
+			private var _textFlow:TextFlow = null;
+			private var _myContainerController:MyContainerController=null;
+			// container to hold the text
+			private var _container:Sprite = null;
+			// ///////////////////////////////////////
+			// data providers for enumerated list boxes
+			// ///////////////////////////////////////
+			static private const textAlignData:Array = [
+				{ label:"Justify",	data:TextAlign.JUSTIFY},
+				{ label:"Left",		data:TextAlign.LEFT},
+				{ label:"Right",	data:TextAlign.RIGHT},
+				{ label:"Center",	data:TextAlign.CENTER},
+				{ label:"End",		data:TextAlign.END},
+				{ label:"Start",	data:TextAlign.START}
+			];
+			static private const verticalAlignData:Array = [
+				{ label:"Bottom",	data:VerticalAlign.BOTTOM },
+				{ label:"Justify",	data:VerticalAlign.JUSTIFY },
+				{ label:"Middle",	data:VerticalAlign.MIDDLE },
+				{ label:"Top",		data:VerticalAlign.TOP }
+			];
+			
+			static private const blockProgressionData:Array = [
+				{ label:"TopToBottom",	data:BlockProgression.TB },
+				{ label:"RightToleft",	data:BlockProgression.RL }
+			];
+			
+			static private const directionData:Array = [
+				{ label:"LeftToRight",	data:Direction.LTR },
+				{ label:"RightToleft",	data:Direction.RTL }
+			];
+			
+			/** 
+			 * initialization
+			 */
+			private function init():void
+			{
+				// create a sprite to hold the TextLines
+				_container = new Sprite();
+				textArea.rawChildren.addChild(_container);
+				
+				fontFamily.dataProvider = populateFontFamily();
+				
+				versionInfo.text = "Vellum: 3.x"  + (Configuration.tlf_internal::debugCodeEnabled ? " Debug" : " Release") 
+					+ ", Flex: " + mx_internal::VERSION
+					+ ", Player: " + Capabilities.version;
+			}
+			
+			/**
+			* Create an array of available font families
+			*/ 
+			static private function populateFontFamily():Array
+			{
+				// really this returns an array of fonts - would be nice to strip it down to just the families
+				var fonts:Array = Font.enumerateFonts(true);
+				var fontfamily:Array = new Array();
+				fonts.sortOn("fontName", Array.CASEINSENSITIVE);
+				for(var i:int = 0; i< fonts.length; i++)
+				{
+					// trace(fonts[i].fontName);
+					fontfamily.push({label: fonts[i].fontName, data: fonts[i].fontName});
+				}
+				return fontfamily;
+			}
+			
+			/** called to set the size of this panel */
+			public function setSize(w:int,h:int):void
+			{
+				this.width = w;
+				this.height = h;
+				textArea.width = width;
+				textArea.height = height > bottomTabs.height ? this.height-bottomTabs.height : 0;
+				if (_textFlow)
+				{
+					_textFlow.flowComposer.getControllerAt(0).setCompositionSize(textArea.width,textArea.height);
+					_textFlow.flowComposer.updateAllControllers();
+				}
+			}
+			
+			/** called when the bottom tabs finally gets sized. */
+			private function bottomTabsResize():void
+			{
+				setSize(width,height);
+			}
+			
+			/** The TextFlow to edit. */
+			public function get textFlow():TextFlow
+			{ return _textFlow; }
+			
+			public function set textFlow(newFlow:TextFlow):void
+			{
+				// clear any old flow if present
+				if (_textFlow)
+				{
+					_textFlow.flowComposer = null;
+					_textFlow = null;
+				}
+				_textFlow = newFlow;
+				if (_textFlow)
+				{
+					_myContainerController=new MyContainerController(_container,textArea.width,textArea.height);
+					_textFlow.flowComposer.addController(_myContainerController);
+					
+					// setup event listeners for selection changed and ILG loaded
+					_textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,selectionChangeListener,false,0,true);
+					_textFlow.addEventListener(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,graphicStatusChangeEvent,false,0,true);
+					
+					// make _textFlow editable with undo 
+					_textFlow.interactionManager = new EditManager(new UndoManager());
+					// initialize with a selection before the first character
+					_textFlow.interactionManager.selectRange(0,0);
+					
+					// compose the new textFlow and give it focus
+					_textFlow.flowComposer.updateAllControllers();
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			/** Receives an event any time an ILG with a computed size finishes loading. */
+ 			private function graphicStatusChangeEvent(evt:StatusChangeEvent):void
+			{
+				// recompose if the evt is from an element in this textFlow
+				if (_textFlow && evt.element.getTextFlow() == _textFlow)
+					_textFlow.flowComposer.updateAllControllers();
+			}	
+			
+			/** Receives an event any time the selection is changed.  Update the UI */
+			private function selectionChangeListener(e:SelectionEvent):void
+ 			{
+ 				var selectionState:SelectionState = e.selectionState;
+ 				var selectedElementRange:ElementRange = ElementRange.createElementRange(selectionState.textFlow, selectionState.absoluteStart, selectionState.absoluteEnd);
+ 				// set display according to the values at the beginning of the selection range.  For point selection/characterFormat use getCommonCharacterFormat as that tracks pending attributes waiting for the next character
+ 				var characterFormat:ITextLayoutFormat = _textFlow.interactionManager.activePosition == _textFlow.interactionManager.anchorPosition ? _textFlow.interactionManager.getCommonCharacterFormat() : selectedElementRange.characterFormat;
+ 				var paragraphFormat:ITextLayoutFormat = selectedElementRange.paragraphFormat;
+ 				var containerFormat:ITextLayoutFormat = selectedElementRange.containerFormat;
+ 				
+ 				updateComboBox(fontFamily,characterFormat.fontFamily);
+ 				fontSize.text = characterFormat.fontSize.toString();
+ 				lineHeight.text = characterFormat.lineHeight.toString();
+ 				
+ 				updateComboBox(textAlign,paragraphFormat.textAlign);
+ 				textIndent.text = paragraphFormat.textIndent.toString();
+ 				
+ 				columnCount.text = containerFormat.columnCount.toString();
+ 				columnGap.text = containerFormat.columnGap.toString();
+ 				updateComboBox(verticalAlign,containerFormat.verticalAlign);
+ 				
+ 				updateComboBox(blockProgression,_textFlow.computedFormat.blockProgression);
+ 				updateComboBox(directionBox,_textFlow.computedFormat.direction);
+ 			}
+ 			
+ 			/** Helper function to update a comboBox in the UI */
+ 			private function updateComboBox(box:ComboBox,val:String):void
+ 			{
+ 				for (var i:int = 0; i < box.dataProvider.length; i++)
+ 				{
+ 					if (box.dataProvider[i].data == val)
+ 					{
+ 						box.selectedIndex = i;
+ 						return;
+ 					}
+ 				}
+ 				box.text = val;
+ 			}
+ 			
+ 			/**
+ 			 * These functions are helpers for the various widgets to actually perform the operations on the TextFlow
+ 			 */
+			private function changeFontFamily(newFontFamily:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.fontFamily = newFontFamily;
+					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			private function changeFontSize(newFontSize:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.fontSize = newFontSize;
+					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			private function changeLeading(newLeading:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.lineHeight = newLeading;
+					IEditManager(_textFlow.interactionManager).applyLeafFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeTextAlign(newAlign:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var pf:TextLayoutFormat = new TextLayoutFormat();
+					pf.textAlign = newAlign;
+					IEditManager(_textFlow.interactionManager).applyParagraphFormat(pf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeTextIndent(newIndent:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var pf:TextLayoutFormat = new TextLayoutFormat();
+					pf.textIndent = newIndent;
+					IEditManager(_textFlow.interactionManager).applyParagraphFormat(pf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeColumnCount(newCount:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.columnCount = newCount;
+					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeColumnGap(newGap:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.columnGap = newGap;
+					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeVerticalAlign(newAlign:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.verticalAlign = newAlign;
+					IEditManager(_textFlow.interactionManager).applyContainerFormat(cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			private function changeBlockProgression(newProgression:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var cf:TextLayoutFormat = new TextLayoutFormat();
+					cf.blockProgression = newProgression;
+					IEditManager(_textFlow.interactionManager).applyFormatToElement(_textFlow,cf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+			
+			/** Set direction on the rootElement.  This effects both columnDirection and default reading order. */
+			private function changeDirection(newDirection:String):void
+			{
+				if (_textFlow && _textFlow.interactionManager is IEditManager)
+				{
+					var pf:TextLayoutFormat = new TextLayoutFormat();
+					pf.direction = newDirection;
+					IEditManager(_textFlow.interactionManager).applyFormatToElement(_textFlow,pf);
+					_textFlow.interactionManager.setFocus();
+				}
+			}
+	
+			protected function doSpell():void
+			{
+				if(spellLang.text)
+					SpellUIForTLF.enableSpelling(_textFlow,spellLang.text );
+				_myContainerController.language=spellLang.text;
+			}
+			
+			protected function undoSpell():void
+			{
+				SpellUIForTLF.disableSpelling(_textFlow);
+				_myContainerController.setFuncsNull();
+			}
+			
+			
+		]]>
+	</mx:Script>
+	<!-- <mx:VBox horizontalScrollPolicy="off" verticalScrollPolicy="off" width="100%" height="100%"> -->
+		<mx:TabNavigator id="bottomTabs" width="100%" creationPolicy="all" paddingLeft="4" paddingBottom="8" backgroundColor="#D9D9D9" color="#202020" horizontalScrollPolicy="on" verticalScrollPolicy="on" resize="bottomTabsResize()">
+			<mx:HBox label="Text" backgroundColor="#D9D9D9" width="496" horizontalScrollPolicy="off" verticalScrollPolicy="off" >
+				<mx:Label text="Font:"/>
+				<mx:ComboBox id="fontFamily" editable="true" enter="changeFontFamily(fontFamily.text)"  close="changeFontFamily(fontFamily.text)" width="200"/>
+				<mx:Label text="Size:"/>
+				<mx:TextInput id="fontSize" enter="changeFontSize(fontSize.text)" width="40"/>
+				<mx:Label text="LineHeight:"/>
+				<mx:TextInput id="lineHeight" enter="changeLeading(lineHeight.text)" width="40"/>
+			</mx:HBox>
+			<mx:HBox label="Para" backgroundColor="#D9D9D9" width="496">
+				<mx:Label text="Alignment:"/>
+				<mx:ComboBox id="textAlign" close="changeTextAlign(textAlign.selectedItem.data)" dataProvider="{textAlignData}"/>
+				<mx:Label text="FirstLineIdent:"/>
+				<mx:TextInput id="textIndent" enter="changeTextIndent(textIndent.text)" width="40"/>
+			</mx:HBox>
+			<mx:HBox label="Container" backgroundColor="#D9D9D9" width="496">
+				<mx:Label text="Columns:"/>
+				<mx:TextInput id="columnCount" toolTip="auto or a number" enter="changeColumnCount(columnCount.text)" width="40"/>
+				<mx:Label text="Gap:"/>
+				<mx:TextInput id="columnGap" toolTip="a number" enter="changeColumnGap(columnGap.text)" width="40"/>
+				<mx:Label text="VerticalAlignment:"/>
+				<mx:ComboBox id="verticalAlign" close="changeVerticalAlign(verticalAlign.selectedItem.data)" dataProvider="{verticalAlignData}"/>
+			</mx:HBox>
+			<mx:HBox label="Flow" backgroundColor="#D9D9D9" width="496">
+				<mx:Label text="Progression:"/>
+				<mx:ComboBox id="blockProgression" close="changeBlockProgression(blockProgression.selectedItem.data)" dataProvider="{blockProgressionData}"/>
+				<mx:Label text="Direction:"/>
+				<mx:ComboBox id="directionBox" close="changeDirection(directionBox.selectedItem.data)" dataProvider="{directionData}"/>
+			</mx:HBox>
+			<mx:HBox label="Version" backgroundColor="#D9D9D9" width="496">
+				<mx:TextInput id="versionInfo" editable="false" width="100%"/>
+			</mx:HBox>
+			<mx:HBox label="Spelling" backgroundColor="#D9D9D9" width="496">
+				<mx:TextInput text="en_US" id="spellLang" editable="true" width="20%"/>
+				<mx:Button id="spellBut" label="Enable Spelling" click="doSpell()"/>
+				<mx:Button id="unspellBut" label="Disable Spelling" click="undoSpell()"/>
+			</mx:HBox>
+		</mx:TabNavigator>
+	<mx:Canvas id="textArea" width="520" height="400"/>
+	<!-- </mx:VBox> -->
+</mx:VBox>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/build.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/build.xml b/Squiggly/ane/Squiggly/build.xml
new file mode 100644
index 0000000..c2d0a5f
--- /dev/null
+++ b/Squiggly/ane/Squiggly/build.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" ?>
+<!--
+
+  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.
+
+-->
+<project default="test" basedir=".">
+
+    <property file="${basedir}/env.properties"/>
+    <property environment="env"/>
+    <property file="${basedir}/local.properties"/>
+    <property file="${basedir}/build.properties"/>
+    <condition property="FLEX_HOME" value="${env.FLEX_HOME}">
+        <isset property="env.FLEX_HOME" />
+    </condition>
+    <condition property="AIR_HOME" value="${env.AIR_HOME}">
+        <isset property="env.AIR_HOME" />
+    </condition>
+
+    <!-- SDK properties -->
+    <property name="FLEX_HOME" value="C:/air3_beta2"/>
+    <property name="AIR_HOME" value="C:/air3_beta2"/>
+	<property name="MXMLC.JAR" value="${FLEX_HOME}/lib/mxmlc.jar"/>
+	<property name="COMPC.JAR" value="${FLEX_HOME}/lib/compc.jar"/>
+	<property name="ADL" value="${AIR_HOME}/bin/adl.exe"/>
+    <property name="ADT.JAR" value="${AIR_HOME}/lib/adt.jar"/>
+	
+    <property name="OUTPUT_DIR" value="libs"/>
+    
+     <target name="init" depends="clean">
+     	<mkdir dir="${OUTPUT_DIR}"/>
+    </target>
+	
+	<target name="compilelinguistics" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="+configname=air"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeLinguisticUtils/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeLinguisticUtils/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${AIR_HOME}/frameworks/libs/air/airglobal.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+		</java>
+	</target>
+	
+	<target name="compileengine" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="+configname=air"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingEngine/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingEngine/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${AIR_HOME}/frameworks/libs/air/airglobal.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+		</java>
+	</target>
+
+	<target name="compileframework" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="+configname=air"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingFramework/src"/>
+			<arg value="-source-path"/>
+			<arg value="../SWCandANE/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingFramework/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${AIR_HOME}/frameworks/libs/air/airglobal.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+		</java>
+	</target>
+
+	<target name="compileui" depends="init">
+		<java jar="${COMPC.JAR}" fork="true" failonerror="true">
+			<arg value="-swf-version"/>
+			<arg value="13"/>
+			<arg value="+flexlib=${FLEX_HOME}/frameworks"/>
+			<arg value="+configname=air"/>
+			<arg value="-source-path"/>
+			<arg value="AdobeSpellingUITLF/src"/>
+			<arg value="-include-sources"/>
+			<arg value="AdobeSpellingUITLF/src"/>
+			<arg value="-external-library-path"/>
+			<arg value="${AIR_HOME}/frameworks/libs/air/airglobal.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeLinguisticUtils.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingEngine.swc"/>
+			<arg value="-external-library-path"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingFramework.swc"/>
+			<arg value="-output"/>
+			<arg value="${OUTPUT_DIR}/AdobeSpellingUITLF.swc"/>
+		</java>
+	</target>
+
+    <target name="test" depends="compilelinguistics, compileengine, compileframework, compileui">
+    </target>
+   
+    <target name="clean" description="clean up">
+    	<delete dir="${OUTPUT_DIR}"/>
+    </target>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension.sln
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension.sln b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension.sln
new file mode 100644
index 0000000..c8694f4
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HunspellNativeExtension", "HunspellNativeExtension\HunspellNativeExtension.vcxproj", "{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Debug|Win32.Build.0 = Debug|Win32
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Debug|x64.ActiveCfg = Debug|x64
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Debug|x64.Build.0 = Debug|x64
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Release|Win32.ActiveCfg = Release|Win32
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Release|Win32.Build.0 = Release|Win32
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Release|x64.ActiveCfg = Release|x64
+		{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.cpp b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.cpp
new file mode 100644
index 0000000..be6902d
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.cpp
@@ -0,0 +1,130 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.cpp
+
+	Author: Masa Hokari <mh...@adobe.com>
+	
+	Source borrowed from LiLO
+*/
+
+
+
+#include "CharConv.h"
+
+#include <iostream>
+#include <cstring>
+#include <stdexcept>
+
+
+#include <wchar.h>
+
+
+
+
+
+
+
+
+// =============================================================================
+
+namespace CharConv
+{
+
+
+// -----------------------------------------------------------------------------
+
+static PlatformEncoding getPlatformEncoding(const Encoding enc)
+{
+	switch(enc)
+	{
+	case Encoding_UTF8:						return CP_UTF8;
+	case Encoding_UTF16:					return 1200;
+	case Encoding_CurrentLocaleSpecific:	return CP_ACP;	// CP_THREAD_ACP
+	}
+	return 0;
+
+}
+
+// -----------------------------------------------------------------------------
+
+static const std::string _makeString(wchar_t const* const src, Encoding enc)
+{
+	const UINT cp = getPlatformEncoding(enc);
+	const int numOfUnitsReqed = ::WideCharToMultiByte(
+		/* UINT		codePage			*/	cp,
+		/* DWORD	dwFlags				*/	0,
+		/* LPCWSTR	lpWideCharStr		*/	src,
+		/* int		cchWideChar			*/	-1,
+		/* LPSTR	lpMultiByteStr		*/	NULL,
+		/* int		cbMultiByte			*/	0,
+		/* LPCSTR	lpDefaultChar		*/	NULL,
+		/* LPBOOL	lpUsedDefaultChar	*/	NULL);
+	if (numOfUnitsReqed == 0)
+	{
+		const DWORD err = GetLastError();
+		std::string dst1("");
+		return dst1;
+		//throw std::runtime_error("Unable to calculate string length");
+	}
+
+	const LPSTR buf = new CHAR [numOfUnitsReqed];
+	const int numOfUnitsUsed = ::WideCharToMultiByte(
+		/* UINT		codePage			*/	cp,
+		/* DWORD	dwFlags				*/	0,
+		/* LPCWSTR	lpWideCharStr		*/	src,
+		/* int		cchWideChar			*/	-1,
+		/* LPSTR	lpMultiByteStr		*/	buf,
+		/* int		cbMultiByte			*/	numOfUnitsReqed,
+		/* LPCSTR	lpDefaultChar		*/	NULL,
+		/* LPBOOL	lpUsedDefaultChar	*/	NULL);
+	if (numOfUnitsUsed == 0)
+	{
+		const DWORD err = GetLastError();
+		delete[] buf;
+		std::string dst1("");
+		return dst1;
+		//throw std::runtime_error("Unable to convert to multi-byte string");
+	}
+
+	std::string dst(buf);
+	delete[] buf;
+	return dst;
+
+}
+
+// -----------------------------------------------------------------------------
+
+
+const std::string  makeString(wchar_t const* src, Encoding enc)
+{
+	return _makeString(src, enc);
+}
+
+
+
+
+}
+// -----------------------------------------------------------------------------
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.h b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.h
new file mode 100644
index 0000000..bfaabd0
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/CharConv.h
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.h
+
+	Author: Masa Hokari <mh...@adobe.com>
+*/
+
+#ifndef __CHARCONV_H__
+#define __CHARCONV_H__
+
+#if defined(WIN_PLATFORM)
+	#include <windows.h>
+#endif
+
+
+
+
+
+#include <string>
+
+namespace CharConv
+{
+
+// -----------------------------------------------------------------------------
+
+enum Encoding
+{
+	Encoding_Invalid,
+	Encoding_UTF8,
+	Encoding_UTF16,
+	Encoding_UTF32,
+	Encoding_CurrentLocaleSpecific
+};
+
+#if defined(WIN_PLATFORM)
+	typedef UINT PlatformEncoding;			// WideCharToMultiByte
+
+#endif
+
+
+
+const std::string  makeString(wchar_t const* src, Encoding enc = Encoding_CurrentLocaleSpecific);
+
+
+
+
+
+
+// -----------------------------------------------------------------------------
+
+}	// namespace
+
+#endif

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.cpp b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.cpp
new file mode 100644
index 0000000..af1478d
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.cpp
@@ -0,0 +1,281 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.cpp
+
+	Author: Sudhakar Pandey <su...@adobe.com>
+*/
+
+
+#include <iostream>
+#include <cstring>
+#include <stdexcept>
+#include "EncConv.h"
+
+    #include "unicode/ucnv.h"   //Adding this as an alternative to native iconv library
+    #include "unicode/ustring.h"   //Adding this as an alternative to native iconv library
+
+#ifndef MAX
+		#define	MAX(a,b) (((a)>(b))?(a):(b))
+	#endif /* MAX */
+// =============================================================================
+
+namespace EncConv
+{
+
+// -----------------------------------------------------------------------------
+
+U16Char_t* convSpecialCharsInU16Str(const U16Char_t* src)
+{
+	const LM_UInt32 srcLen = GetNumOfUnits(src);
+	U16Char_t* pdst = new U16Char_t [srcLen + 1];
+	 
+	LM_UInt32 i;
+	for(i = 0; i < srcLen; ++i)
+	{
+		U16Char_t c = src[i];
+		switch (c)
+		{
+		case 0x2018:		// U+2018: Left Single Quotation Mark
+		case 0x2019:		// U+2019: Right Single Quotation Mark
+					c = '\'';	break;
+		case 0x201C:		// U+201C: Left Double Quotation Mark
+		case 0x201D:		// U+201D: Right Double Quotation Mark
+					c = '"';	break;
+		}
+		pdst[i] = c;
+	}
+	pdst[i] = 0;
+	return pdst;
+	//delete[] pdst;
+	//should be deleted by calling releaseU16CharString() function.
+}
+
+const char * getPlatformEncoding(const char* enc)
+{
+	//If encoding is null or not specified then try the default encoding "ISO-8859-1"
+	if(strlen(enc) == 0)
+		return "ISO-8859-1";
+	if(strcmp(enc,"ISO8859-1") == 0)
+		return "ISO-8859-1";
+	else if (strcmp(enc,"ISO8859-2") == 0)
+		return "ISO-8859-2";
+	else if (strcmp(enc,"ISO8859-3") == 0)
+		return "ISO-8859-3";
+	else if (strcmp(enc,"ISO8859-4") == 0)
+		return "ISO-8859-4";
+	else if (strcmp(enc,"ISO8859-5") == 0)
+		return "ISO-8859-5";
+	else if (strcmp(enc,"ISO8859-6") == 0)
+		return "ISO-8859-6";
+	else if (strcmp(enc,"ISO8859-7") == 0)
+		return "ISO-8859-7";
+	else if (strcmp(enc,"ISO8859-8") == 0)
+		return "ISO-8859-8";
+	else if (strcmp(enc,"ISO8859-9") == 0)
+		return "ISO-8859-9";
+	else if (strcmp(enc,"ISO8859-10") == 0)
+		return "ISO-8859-10";
+	else if (strcmp(enc,"KOI8-R") == 0)
+		return "KOI8-R";
+	else if (strcmp(enc,"KOI8-U") == 0)
+		return "KOI8-U";
+	else if (strcmp(enc,"microsoft-cp1251") == 0)
+		return "cp1251";
+	else if (strcmp(enc,"ISO8859-13") == 0)
+		return "ISO-8859-13";
+	else if (strcmp(enc,"ISO8859-14") == 0)
+		return "ISO-8859-14";
+	else if (strcmp(enc,"ISO8859-15") == 0)
+		return "ISO-8859-15";
+	else if (strcmp(enc,"ISCII-DEVANAGARI") == 0)
+		return "ibm-1137";
+	else if (strcmp(enc,"TIS620-2533") == 0)
+		return "TIS-620";
+	else if (strcmp(enc,"UTF-8") == 0)
+		return "UTF-8";
+	else
+		return enc;
+}
+
+
+const std::string convU16StrToCharStr(const U16Char_t* src, const char* Encoding)
+{
+	//static char const* const tocode = CHARCONV_ICONV_UTF16;
+	char const* const tocode = getPlatformEncoding(Encoding);
+    
+    UErrorCode status = U_ZERO_ERROR;
+
+#ifdef ENCCONV_DEBUG
+	std::cout << "\t" "convString" << std::endl;
+	std::cout << "\t\t" "tocode   = " << tocode   << std::endl;
+	//std::cout << "\t\t" "fromcode = " << fromcode << std::endl;
+#endif
+
+	//iconv_t cd = iconv_open(tocode, fromcode);
+    // Initializing ICU converter
+	UConverter *conv = ucnv_open(tocode, &status);
+
+#ifdef CHARCONV_DEBUG
+	std::cout << "\t\t" "aft ucnv_open: status = " << status << std::endl;
+#endif
+	if (conv == NULL)
+	{ // try default encoding "ISO-8859-1"
+		//throw std::runtime_error("Unable to create Unicode converter object");
+		status = U_ZERO_ERROR;
+		conv = ucnv_open("ISO-8859-1", &status);
+	}
+
+	//still if conv is null simply return blank string
+
+	if (conv == NULL)
+	{ 
+		return std::string("");
+	}
+
+	U16Char_t const* srcWrk = src;
+	const size_t srcSizeInUnits = GetNumOfUnits(src);
+	const size_t srcSizeInBytes = srcSizeInUnits * sizeof(U16Char_t);
+	const size_t dstSizeInBytes = MAX(256, (srcSizeInUnits + 1)) * 4;	// How much byte buffer is needed? (UTF16 --> MBCS)
+	char* dst = new char [dstSizeInBytes];
+	if(dst==NULL) return std::string("");
+
+	char* dstWrk =(char*)(dst);
+	size_t srcLeftInBytes = srcSizeInBytes;
+	size_t dstLeftInBytes = dstSizeInBytes - sizeof(char);
+    status = U_ZERO_ERROR;
+
+		ucnv_fromUChars(conv, dstWrk, dstLeftInBytes, (UChar*)srcWrk, -1, &status);
+		U16Char_t* reverseConvertedVal = convCharStrToU16Str(dstWrk,Encoding);
+		if(strcmp((char*)reverseConvertedVal,(char*)src)!=0)
+		{
+			EncConv::releaseU16Str(reverseConvertedVal);
+	        delete[] dst;
+			return std::string("");
+		}
+		EncConv::releaseU16Str(reverseConvertedVal);
+		
+	
+#ifdef CHARCONV_DEBUG
+		std::cout << "\t\t" "aft iconv: status = " << status << std::endl;
+#endif
+		if (status != U_ZERO_ERROR )
+		{
+			//	throw std::runtime_error("Unable to convert to string");
+			*dstWrk = 0;
+		}
+
+
+		std::string dst2(dst);
+
+        delete[] dst;
+	//const int err = iconv_close(cd);
+
+    ucnv_close(conv);
+
+	//if (err == -1)
+	//	throw std::runtime_error("Unable to deallocate iconv_t object");
+
+        return dst2;
+}
+
+U16Char_t* convCharStrToU16Str(const char* src, const char* Encoding)
+{
+
+	//static char const* const tocode = CHARCONV_ICONV_UTF16;
+	char const* const fromcode = getPlatformEncoding(Encoding);
+    
+    UErrorCode status = U_ZERO_ERROR;
+
+#ifdef ENCCONV_DEBUG
+	std::cout << "\t" "convString" << std::endl;
+	//std::cout << "\t\t" "tocode   = " << tocode   << std::endl;
+	std::cout << "\t\t" "fromcode = " << fromcode << std::endl;
+#endif
+
+	//iconv_t cd = iconv_open(tocode, fromcode);
+    // Initializing ICU converter
+	UConverter *conv = ucnv_open(fromcode, &status);
+
+#ifdef CHARCONV_DEBUG
+	std::cout << "\t\t" "aft ucnv_open: status = " << status << std::endl;
+#endif
+	if (conv == NULL)
+	{ // try default encoding "ISO-8859-1"
+		//throw std::runtime_error("Unable to create Unicode converter object");
+		conv = ucnv_open("ISO-8859-1", &status);
+	}
+
+	
+
+	char const* srcWrk = src;
+	const size_t srcSizeInBytes = std::strlen(src);
+	const size_t dstSizeInBytes = MAX(256, (srcSizeInBytes + 1)) * sizeof(U16Char_t);
+	U16Char_t* dst = new U16Char_t [dstSizeInBytes / sizeof(U16Char_t)];
+	U16Char_t* dstWrk = dst;
+	size_t srcLeftInBytes = srcSizeInBytes;
+	size_t dstLeftInBytes = dstSizeInBytes - sizeof(U16Char_t);
+
+    status = U_ZERO_ERROR;
+
+	//still if conv is null simply return blank string
+
+	if (conv == NULL)
+	{ 
+		dst[0] = NULL;
+		return dst;
+	}
+
+	ucnv_toUChars(conv, (UChar *) dstWrk, dstLeftInBytes, (char*)srcWrk, srcLeftInBytes, &status);
+	
+#ifdef CHARCONV_DEBUG
+		std::cout << "\t\t" "aft iconv: status = " << status << std::endl;
+#endif
+		if (status != U_ZERO_ERROR )
+		{
+			//	throw std::runtime_error("Unable to convert to string");
+			*dstWrk = 0;
+		}
+
+
+	//const int err = iconv_close(cd);
+
+    ucnv_close(conv);
+
+	//if (err == -1)
+	//	throw std::runtime_error("Unable to deallocate iconv_t object");
+
+	return dst;
+
+}
+
+void releaseU16Str(const U16Char_t* buf)
+{
+		if(buf != NULL)
+		{
+			delete[] buf;
+			buf = NULL;
+		}
+		return;
+}
+
+}// namespace
+// -----------------------------------------------------------------------------
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.h b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.h
new file mode 100644
index 0000000..d7ba076
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/EncConv.h
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+	CharConv.h
+
+	Author: Sudhakar Pandey <su...@adobe.com>
+*/
+
+#ifndef __ENCCONV_H__
+#define __ENCCONV_H__
+
+
+#include <string>
+#include "unicode/ucnv.h"
+typedef unsigned short U16Char_t;
+typedef unsigned long	LM_UInt32;
+
+namespace EncConv
+{
+	template<class CharType>
+	static size_t GetNumOfUnits(CharType const* src)
+	{
+		size_t numOfUnits = 0;
+		while (*src++ != 0)
+			++numOfUnits;
+
+		return numOfUnits;
+	}
+
+	const char * getPlatformEncoding(char* enc);
+	const std::string convU16StrToCharStr(const U16Char_t* src, const char* Encoding);
+	U16Char_t* convCharStrToU16Str(const char* src, const char* Encoding);
+
+	U16Char_t* convSpecialCharsInU16Str( const U16Char_t* src); // caller need not allocate memory for the return value U16Char_t* 
+	void releaseU16Str(const U16Char_t* buf);
+
+}	// namespace
+
+#endif

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
new file mode 100644
index 0000000..810db5c
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.cpp
@@ -0,0 +1,334 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// This is the main DLL file.
+
+//#include "stdafx.h"
+#include <windows.h> 
+#include "EncConv.h"
+#include "win\Utilities.h"
+#include <stdio.h> 
+#include "HunspellNativeExtension.h"
+
+typedef Hunspell * (__cdecl *HUNSPELL_INIT)(char *, char*); 
+typedef int (__cdecl *HUNSPELL_SPELL)(void *, char*); 
+typedef int (__cdecl *HUNSPELL_SUGGEST)(void *, char*, char ***); 
+typedef void (__cdecl *HUNSPELL_FREE_LIST)(void *, char***, int); 
+typedef char * (__cdecl *HUNSPELL_GET_ENCODING)(void *);
+typedef void (__cdecl * HUNSPELL_UNINIT)(void *);
+HINSTANCE hinstLib; 
+
+FREObject talkBack(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+	const uint8_t *locale = 0;
+	const uint8_t *inpWord = 0;
+	uint32_t len = 0;
+	FREObject retObj=0;
+
+	//get first argument
+	if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+	return retObj;
+
+	FRENewObjectFromUTF8((uint32_t)(strlen((char *)inpWord)),(const uint8_t*)(inpWord), &retObj);
+
+	return retObj;
+	
+}
+
+
+FREObject initHunspellObject(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){
+	const uint8_t *locale = 0;
+	const uint8_t *dictionaryPath = 0;
+	uint32_t len = -1;
+	FREObject retObj=0;
+	Hunspell * hunspellObject;
+	BOOL  fRunTimeLinkSuccess = FALSE; 
+	//get first argument
+	if(FREGetObjectAsUTF8(argv[1], &len, &dictionaryPath) != FRE_OK)
+	return retObj;
+	len = 0;
+	
+	//get second argument
+	if(FREGetObjectAsUTF8(argv[0], &len, &locale) != FRE_OK)
+	return retObj;
+
+	//check in cache and return if already present
+	if(!(Hunspell_cache.find(std::string((char *)locale))==Hunspell_cache.end()))
+		{
+			FRENewObjectFromInt32(HUNSPELL_INIT_SUCCESS, &retObj);
+			return retObj;
+		}
+	
+	U16Char_t * dic_path_U16= EncConv::convCharStrToU16Str((char *)dictionaryPath, "UTF-8");
+	U16Char_t *locale_U16= EncConv::convCharStrToU16Str((char *)locale, "UTF-8");
+	std::wstring aff_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"\\Dictionaries\\")+std::wstring((wchar_t *)locale_U16)+std::wstring(L"\\")+std::wstring((wchar_t *)locale_U16)+std::wstring(L".aff");
+	std::wstring dic_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"\\Dictionaries\\")+std::wstring((wchar_t *)locale_U16)+std::wstring(L"\\")+std::wstring((wchar_t *)locale_U16)+std::wstring(L".dic");
+	std::wstring lib_file= std::wstring((wchar_t *)dic_path_U16)+std::wstring(L"\\libhunspell.dll");
+	
+	EncConv::releaseU16Str(dic_path_U16);
+	EncConv::releaseU16Str(locale_U16);
+	//creating OS specific aff,dic file paths refer: DanishOS Issue of CS6 AHP 
+	std::string aff_file_U8= makeString(aff_file.c_str());
+	std::string dic_file_U8= makeString(dic_file.c_str());
+	
+	//make the file url's
+	std::string lib_file_U8= std::string((char *)dictionaryPath)+std::string("\\libhunspell.dll");
+	
+	//check for file is present
+
+	if( (FileExists(aff_file) && FileExists(dic_file) && FileExists(lib_file)) == false )
+	{
+		FRENewObjectFromInt32(RESOURCE_FILES_MISSING, &retObj);
+		return retObj;
+	}
+
+
+	LPCTSTR lib_file_lpstring= (wchar_t *)lib_file.c_str();
+	
+	//make a new hunspell object
+	hinstLib = LoadLibrary(lib_file_lpstring); 
+	if (hinstLib != NULL) 
+    { 
+       HUNSPELL_INIT initAdd = (HUNSPELL_INIT) GetProcAddress(hinstLib, "hunspell_initialize"); 
+		 
+        // If the function address is valid, call the function.
+ 
+        if (NULL != initAdd) 
+        {
+            fRunTimeLinkSuccess = TRUE;
+          hunspellObject = (initAdd) ((char *)aff_file_U8.c_str(), (char *)dic_file_U8.c_str()); 
+        }
+
+    } 
+
+//add to hunspell cache	
+	if(Hunspell_cache.find(std::string((char *)locale))==Hunspell_cache.end())	
+		Hunspell_cache[std::string((char *)locale)]= hunspellObject;
+	
+	if(hunspellObject)
+	{
+		FRENewObjectFromInt32(HUNSPELL_INIT_SUCCESS, &retObj);
+	}
+	else
+	{
+		FRENewObjectFromInt32(HUNSPELL_INIT_FAIL, &retObj);
+	}
+	return retObj;
+}
+
+FREObject checkWord(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+	const uint8_t *locale = 0;
+	const uint8_t *inpWord = 0;
+	uint32_t len = -1;
+	FREObject retObj=0;
+	int rv=0;
+
+	U16Char_t* inpWordU16 = NULL;
+	std::string  inpWordDictEncoded;
+	bool isConversionUnSuccesful=false;
+	//get first argument
+	if(FREGetObjectAsUTF8(argv[1], &len, &locale) != FRE_OK)
+	return retObj;
+	len = 0;
+	
+	//get second argument
+	if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+	return retObj;
+
+	//get the hunspell object from cache
+	Hunspell * hunspellObject=getHunspellObject(std::string((char *)locale));
+		
+	if(!hunspellObject) 
+		return retObj;
+		
+	//convert input utf8 to u16 string
+	inpWordU16 = EncConv::convCharStrToU16Str((char *)inpWord, "UTF-8");
+
+	//get dictionary encoding
+	HUNSPELL_GET_ENCODING getEncAdd=(HUNSPELL_GET_ENCODING) GetProcAddress(hinstLib, "hunspell_get_dic_encoding");
+	char * m_MainEncoding= (getEncAdd)(hunspellObject);
+
+	//convert u16 to dictionary encoding
+	inpWordDictEncoded=EncConv::convU16StrToCharStr(inpWordU16,m_MainEncoding);
+
+	if(inpWordDictEncoded.length()==0)
+	{
+		isConversionUnSuccesful = true;
+	}
+
+	//Get spellAddress
+	HUNSPELL_SPELL spellAdd= (HUNSPELL_SPELL) GetProcAddress(hinstLib, "hunspell_spell");
+
+	//Do spell check with converted word else try with UTF-8
+	if((!isConversionUnSuccesful) )
+	{
+		rv= (spellAdd)(hunspellObject, (char * )inpWordDictEncoded.c_str());
+	}
+	else
+	{
+		rv= (spellAdd)(hunspellObject, (char * )inpWord);
+	}
+		
+	//return results
+	FRENewObjectFromInt32(rv, &retObj);
+	EncConv::releaseU16Str(inpWordU16);
+	 return retObj;
+}
+
+FREObject getSuggestions(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
+	const uint8_t *locale = 0;
+	const uint8_t *inpWord = 0;
+	uint32_t len = -1;
+	FREObject retObj=0;
+	FREObject oneSuggestion=0;
+
+	U16Char_t* inpWordU16 = NULL;
+	std::string  inpWordDictEncoded;
+	bool isConversionUnSuccesful=false;
+	char * oneSuggestionEncoded=NULL;
+	U16Char_t * oneSuggestionU16=NULL;
+	std::string oneSuggestionU8;
+
+	//assign memory to retobj
+	FRENewObject((const uint8_t*)"Array", 0, NULL, &retObj, 0);
+
+	//get first argument
+	if(FREGetObjectAsUTF8(argv[1], &len, &locale) != FRE_OK)
+	return retObj;
+	len = 0;
+	
+	//get second argument
+	if(FREGetObjectAsUTF8(argv[0], &len, &inpWord) != FRE_OK)
+	return retObj;
+	
+	//get the hunspell object from cache
+	Hunspell * hunspellObject=getHunspellObject(std::string((char *)locale));
+		
+	if(!hunspellObject) return retObj;
+	
+	//convert input utf8 to u16 string
+	inpWordU16 = EncConv::convCharStrToU16Str((char *)inpWord, "UTF-8");
+
+	//get dictionary encoding
+	HUNSPELL_GET_ENCODING getEncAdd=(HUNSPELL_GET_ENCODING) GetProcAddress(hinstLib, "hunspell_get_dic_encoding");
+	char * m_MainEncoding= (getEncAdd)(hunspellObject);
+
+	//convert u16 to dictionary encoding
+	inpWordDictEncoded=EncConv::convU16StrToCharStr(inpWordU16,m_MainEncoding);
+
+	if(inpWordDictEncoded.length()==0)
+	{
+		isConversionUnSuccesful = true;
+	}
+
+	//get suggestAddress &freelistAddress
+	HUNSPELL_SUGGEST suggestAdd= (HUNSPELL_SUGGEST) GetProcAddress(hinstLib, "hunspell_suggest");
+	HUNSPELL_FREE_LIST freeListAdd= (HUNSPELL_FREE_LIST) GetProcAddress(hinstLib, "hunspell_free_list");
+	
+	char** suggList = NULL;
+	int numSugg = 0;
+
+	//Try getting suggestions with encoded word else try with UTF8
+	if(suggestAdd && !isConversionUnSuccesful)
+	{
+		numSugg = (suggestAdd)(hunspellObject,(char *) (inpWordDictEncoded.c_str()),&suggList);
+	}
+	else
+	{
+		numSugg = (suggestAdd)(hunspellObject,(char *) (inpWord),&suggList);
+	}
+	
+
+	if(numSugg)
+				{
+					FRESetArrayLength( retObj, numSugg );
+					
+					for(int iCount=0; iCount <numSugg; iCount++)
+					{
+						oneSuggestionEncoded=suggList[iCount];
+						oneSuggestionU16=EncConv::convCharStrToU16Str(oneSuggestionEncoded, m_MainEncoding);
+						oneSuggestionU8= EncConv::convU16StrToCharStr(oneSuggestionU16, "UTF-8");
+						FRENewObjectFromUTF8((uint32_t)(oneSuggestionU8.length()),(const uint8_t*)(oneSuggestionU8.c_str()), &oneSuggestion);
+						FRESetArrayElementAt(retObj, iCount, oneSuggestion);
+						EncConv::releaseU16Str(oneSuggestionU16);
+					}
+					(freeListAdd)(hunspellObject, &suggList,numSugg);
+					
+				}
+	EncConv::releaseU16Str(inpWordU16);
+	return retObj;
+}
+
+Hunspell * getHunspellObject(std::string locale)
+{
+	Hunspell_cache_iterator iter;
+	if((iter=Hunspell_cache.find(locale)) == Hunspell_cache.end() )
+		return NULL;
+	else
+		return iter->second;
+}
+
+void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, 
+						uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet)
+{
+	*numFunctionsToTest = 4;
+	FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*5);
+	
+	func[0].name = (const uint8_t*)"talkBack";
+	func[0].functionData = NULL;
+	func[0].function = &talkBack;
+
+	func[1].name = (const uint8_t*)"initHunspellObject";
+	func[1].functionData = NULL;
+	func[1].function = &initHunspellObject;
+
+	func[2].name = (const uint8_t*)"checkWord";
+	func[2].functionData = NULL;
+	func[2].function = &checkWord;
+
+	func[3].name = (const uint8_t*)"getSuggestions";
+	func[3].functionData = NULL;
+	func[3].function = &getSuggestions;
+
+	*functionsToSet = func;
+}
+
+void ContextFinalizer(FREContext ctx) {
+	return;
+}
+
+__declspec(dllexport) void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, 
+					FREContextFinalizer* ctxFinalizerToSet) {
+	*extDataToSet = NULL;
+	*ctxInitializerToSet = ContextInitializer;
+	*ctxFinalizerToSet = ContextFinalizer;
+}
+
+__declspec(dllexport) void ExtFinalizer(void* extData) {
+	HUNSPELL_UNINIT uninitAdd= (HUNSPELL_UNINIT) GetProcAddress(hinstLib, "hunspell_uninitialize");
+	//clear all hunspell cache 
+	for(Hunspell_cache_iterator hunspell_cache_iter= Hunspell_cache.begin(); hunspell_cache_iter!=Hunspell_cache.end(); hunspell_cache_iter++)
+	{
+		(uninitAdd)(hunspell_cache_iter->second);//uninitialize hunspell objects properly
+		hunspell_cache_iter->second=NULL;
+	}
+	Hunspell_cache.clear();
+	FreeLibrary(hinstLib);//unload hunspell dll
+	return;
+}
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
new file mode 100644
index 0000000..24a27a4
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.h
@@ -0,0 +1,54 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+#include "FlashRuntimeExtensions.h"
+
+#include "hunspelldll.h"
+#include "hunspell.hxx"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <map>
+
+#define HUNSPELL_INIT_FAIL -1
+#define RESOURCE_FILES_MISSING -2
+
+#define HUNSPELL_INIT_SUCCESS 1
+
+
+typedef std::map< std::string, Hunspell * > Hunspell_cache_type;
+typedef std::map< std::string, Hunspell * >::iterator Hunspell_cache_iterator;
+
+static Hunspell_cache_type Hunspell_cache;
+
+extern "C" __declspec(dllexport) void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, 
+					FREContextFinalizer* ctxFinalizerToSet);
+extern "C" __declspec(dllexport) void ExtFinalizer(void* extData);
+
+extern "C"  __declspec(dllexport) FREObject talkBack(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
+
+extern "C"  __declspec(dllexport) FREObject initHunspellObject(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
+
+extern "C"  __declspec(dllexport) FREObject checkWord(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
+
+extern "C"  __declspec(dllexport) FREObject getSuggestions(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
+
+Hunspell * getHunspellObject(std::string locale);
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.vcxproj
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.vcxproj b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.vcxproj
new file mode 100644
index 0000000..6ad5471
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/HunspellNativeExtension.vcxproj
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{F99D7AAC-1A40-441C-9AC1-E81AE5D6F550}</ProjectGuid>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <Keyword>ManagedCProj</Keyword>
+    <RootNamespace>HunspellNativeExtension</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CLRSupport>false</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CLRSupport>false</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <CLRSupport>false</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <CLRSupport>false</CLRSupport>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;USE_ICU;U_STATIC_IMPLEMENTATION;WIN_PLATFORM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <AdditionalIncludeDirectories>$(SolutionDir)third_party\hunspell\src\win_api;$(SolutionDir)third_party\hunspell\src\hunspell;$(SolutionDir)third_party\agl_tp\agl40\include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>FlashRuntimeExtensions.lib;sicuuc.lib;sicudt.lib;sicuin.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>C:\air3_beta2\lib\win;$(SolutionDir)third_party\agl_tp\agl40\libs\$(Platform)-vc10-$(Configuration)\static\lib\MT;$(SolutionDir)third_party\agl_tp\agl40\libs\data\$(Platform)-vc10\lilohunspellplugin\static</AdditionalLibraryDirectories>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;USE_ICU;U_STATIC_IMPLEMENTATION;WIN_PLATFORM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <AdditionalIncludeDirectories>$(SolutionDir)third_party\hunspell\src\win_api;$(SolutionDir)third_party\hunspell\src\hunspell;$(SolutionDir)third_party\agl_tp\agl40\include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>FlashRuntimeExtensions.lib;sicuuc.lib;sicudt.lib;sicuin.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>C:\air3_beta2\lib\win;$(SolutionDir)third_party\agl_tp\agl40\libs\$(Platform)-vc10-$(Configuration)\static\lib\MT;$(SolutionDir)third_party\agl_tp\agl40\libs\data\$(Platform)-vc10\lilohunspellplugin\static</AdditionalLibraryDirectories>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;U_STATIC_IMPLEMENTATION;WIN_PLATFORM;USE_ICU;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <AdditionalIncludeDirectories>$(SolutionDir)third_party\hunspell\src\win_api;$(SolutionDir)third_party\hunspell\src\hunspell;$(SolutionDir)third_party\agl_tp\agl40\include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>FlashRuntimeExtensions.lib;sicuuc.lib;sicudt.lib;sicuin.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>C:\air3_beta2\lib\win;$(SolutionDir)third_party\agl_tp\agl40\libs\$(Platform)-vc10-$(Configuration)\static\lib\MT;$(SolutionDir)third_party\agl_tp\agl40\libs\data\$(Platform)-vc10\lilohunspellplugin\static</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+    </Link>
+    <PostBuildEvent>
+      <Command>
+      </Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;U_STATIC_IMPLEMENTATION;WIN_PLATFORM;USE_ICU;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <AdditionalIncludeDirectories>$(SolutionDir)third_party\hunspell\src\win_api;$(SolutionDir)third_party\hunspell\src\hunspell;$(SolutionDir)third_party\agl_tp\agl40\include</AdditionalIncludeDirectories>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>FlashRuntimeExtensions.lib;sicuuc.lib;sicudt.lib;sicuin.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>C:\air3_beta2\lib\win;$(SolutionDir)third_party\agl_tp\agl40\libs\$(Platform)-vc10-$(Configuration)\static\lib\MT;$(SolutionDir)third_party\agl_tp\agl40\libs\data\$(Platform)-vc10\lilohunspellplugin\static</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
+    </Link>
+    <PostBuildEvent>
+      <Command>
+      </Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="EncConv.h" />
+    <ClInclude Include="FlashRuntimeExtensions.h" />
+    <ClInclude Include="HunspellNativeExtension.h" />
+    <ClInclude Include="resource.h" />
+    <ClInclude Include="win\Utilities.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="EncConv.cpp" />
+    <ClCompile Include="HunspellNativeExtension.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="ReadMe.txt" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/resource.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/resource.h b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/resource.h
new file mode 100644
index 0000000..647a20d
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/resource.h
@@ -0,0 +1,22 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by app.rc

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/win/Utilities.h
----------------------------------------------------------------------
diff --git a/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/win/Utilities.h b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/win/Utilities.h
new file mode 100644
index 0000000..7a6ff5e
--- /dev/null
+++ b/Squiggly/ane/WinDLLHunspellANE/HunspellNativeExtension/win/Utilities.h
@@ -0,0 +1,118 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include<fstream>
+#include <tchar.h>
+using namespace std;
+
+enum Encoding
+{
+	Encoding_Invalid,
+	Encoding_UTF8,
+	Encoding_UTF16,
+	Encoding_UTF32,
+	Encoding_CurrentLocaleSpecific
+};
+
+#if defined(WIN_PLATFORM)
+	typedef UINT PlatformEncoding;			// WideCharToMultiByte
+
+#endif
+
+bool FileExists(const char* inFilePath)
+		{
+			if(inFilePath == NULL) return false;
+			ifstream file(inFilePath, ios::in);
+			if (file.good())
+			{
+				file.close();
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+
+bool FileExists(std::wstring fileURL)
+{
+	FILE* stream = _tfopen(fileURL.c_str(), _T("r"));
+	bool exists = stream != NULL;
+	if (exists)
+		fclose(stream);
+	return exists;
+}
+
+static PlatformEncoding getPlatformEncoding(const Encoding enc)
+{
+	switch(enc)
+	{
+	case Encoding_UTF8:						return CP_UTF8;
+	case Encoding_UTF16:					return 1200;
+	case Encoding_CurrentLocaleSpecific:	return CP_ACP;	// CP_THREAD_ACP
+	}
+	return 0;
+
+}
+
+static const std::string _makeString(wchar_t const* const src, Encoding enc)
+{
+	const UINT cp = getPlatformEncoding(enc);
+	const int numOfUnitsReqed = ::WideCharToMultiByte(
+		/* UINT		codePage			*/	cp,
+		/* DWORD	dwFlags				*/	0,
+		/* LPCWSTR	lpWideCharStr		*/	src,
+		/* int		cchWideChar			*/	-1,
+		/* LPSTR	lpMultiByteStr		*/	NULL,
+		/* int		cbMultiByte			*/	0,
+		/* LPCSTR	lpDefaultChar		*/	NULL,
+		/* LPBOOL	lpUsedDefaultChar	*/	NULL);
+	if (numOfUnitsReqed == 0)
+	{
+		const DWORD err = GetLastError();
+		throw std::runtime_error("Unable to calculate string length");
+	}
+
+	const LPSTR buf = new CHAR [numOfUnitsReqed];
+	const int numOfUnitsUsed = ::WideCharToMultiByte(
+		/* UINT		codePage			*/	cp,
+		/* DWORD	dwFlags				*/	0,
+		/* LPCWSTR	lpWideCharStr		*/	src,
+		/* int		cchWideChar			*/	-1,
+		/* LPSTR	lpMultiByteStr		*/	buf,
+		/* int		cbMultiByte			*/	numOfUnitsReqed,
+		/* LPCSTR	lpDefaultChar		*/	NULL,
+		/* LPBOOL	lpUsedDefaultChar	*/	NULL);
+	if (numOfUnitsUsed == 0)
+	{
+		const DWORD err = GetLastError();
+		throw std::runtime_error("Unable to convert to multi-byte string");
+	}
+
+	std::string dst(buf);
+	delete[] buf;
+	return dst;
+
+}
+
+
+const std::string  makeString(wchar_t const* src, Encoding enc= Encoding_CurrentLocaleSpecific)
+{
+	return _makeString(src, enc);
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/build.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/build.xml b/Squiggly/ane/build.xml
new file mode 100644
index 0000000..73388c2
--- /dev/null
+++ b/Squiggly/ane/build.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" ?>
+<!--
+
+  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.
+
+-->
+<project default="test" basedir=".">
+
+    <target name="test">
+        <ant dir="${basedir}/Squiggly" target="test"/>
+        <ant dir="${basedir}/SWCandANE" target="test"/>
+    </target>
+        
+    <target name="clean" description="clean up">
+        <ant dir="${basedir}/Squiggly" target="clean"/>
+        <ant dir="${basedir}/SWCandANE" target="clean"/>
+    </target>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
new file mode 100644
index 0000000..e4df4bf
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
@@ -0,0 +1,59 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+/* 
+ * @exampleText The following SquigglyTLFExample demonstrates how to use Squiggly UI API to easily integrate Squiggly with your own custom TLF component.
+ * 
+ * Note that the results from this example may differ based on dictionary file.
+ * 
+ * Only one line code is needed:
+ * <ol>
+ *  <li>
+ *  Call Squiggly <code>SpellUIForTLF.enableSpelling</code> method to enable spell checking feature in your TextFlow.
+ *  </li>
+ * </ol>
+ * 
+ * Note: to make this example work properly, please make sure you have the proper dictionary files and AdobeSpellingConfig.xml file in the specified folder 
+ * and put the Squiggly AdobeSpellingUITLF.swc library in your libs folder.
+ */
+package
+{
+	import flash.display.Sprite;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.EditManager;
+	
+	import com.adobe.linguistics.spelling.SpellUIForTLF;
+	
+	public class SquigglyTLFExample extends Sprite
+	{
+		public function SquigglyTLFExample()
+		{
+			var markup:XML = <TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p><span>I know &nbsp;</span><span fontStyle='italic'>Enlish</span><span>. Use the context menu to see the suggestions of the missbelled word.</span></p></TextFlow>;
+			var textFlow:TextFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT);
+			textFlow.flowComposer.addController(new ContainerController(this, 500, 600));
+			textFlow.flowComposer.updateAllControllers();
+			
+			textFlow.interactionManager = new EditManager();
+			
+			SpellUIForTLF.enableSpelling(textFlow, "en_US");
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
new file mode 100644
index 0000000..dc18ae7
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample-app.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 
+ 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.
+ 
+ -->
+<application xmlns="http://ns.adobe.com/air/application/1.5.1">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/1.5.1
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- The application identifier string, unique to this application. Required. -->
+	<id>UserDictionaryExample</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>UserDictionaryExample</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>UserDictionaryExample</name>
+
+	<!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
+	<version>v1</version>
+
+	<!-- Description, displayed in the AIR application installer.
+	     May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flex Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flex Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+	</initialWindow>
+
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+		 specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image48x48></image48x48>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+</application>


[16/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextFilter.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextFilter.as b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextFilter.as
new file mode 100644
index 0000000..e906527
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextFilter.as
@@ -0,0 +1,90 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/* 
+* ToDo: Create ASDoc style comment to generate the API document.
+*/
+package com.adobe.linguistics.utils
+{
+	/**
+	 * <p>This class provides some methods to filter out certain characters from the text.</p>
+	 */
+	public class TextFilter
+	{
+		public static const kTextChar_DiscretionaryHyphen:int 	= 0x00AD;
+		public static const kTextChar_BreakRunInStyle:int		= 0x0003;
+		public static const kTextChar_IndentToHere:int 			= 0x0007;
+		public static const kTextChar_InvisibleSeparator:int 	= 0x2063;
+		public static const kTextChar_ZeroWidthNonJoiner:int 	= 0x200C;
+		public static const kTextChar_ZeroWidthJoiner:int		= 0x200D;
+		public static const kTextChar_ZeroSpaceBreak:int 		= 0x200B;
+		public static const kTextChar_ZeroSpaceNoBreak:int		= 0xFEFF;
+		public static const kTextChar_RightSingleQuotationMark:int = 0x2019;
+		public static const kTextChar_Apostrophe:int			= 0x0027;
+		public static const kTextChar_NoBreakHyphen:int			= 0x2011;
+		public static const kTextChar_UnicodeHyphen:int			= 0x2010;
+		public static const kTextChar_HyphenMinus:int			= 0x002D;
+
+		
+		public function TextFilter()
+		{
+		}
+		
+		public function filterWord(inpWord:String):String
+		{
+			return replaceIgnoredCharacter((removeIgnoredCharacter(inpWord)));	
+		}
+		private function removeIgnoredCharacter(inpWord:String):String
+		{
+			if(!inpWord || inpWord.length<=0) 
+				return inpWord;
+			
+			var tempWord:String= new String;
+
+			for(var i:int=0; i< inpWord.length; i++)
+			{
+				if (   inpWord.charCodeAt(i)==kTextChar_DiscretionaryHyphen
+					|| inpWord.charCodeAt(i)==kTextChar_BreakRunInStyle
+					|| inpWord.charCodeAt(i)==kTextChar_IndentToHere
+					|| inpWord.charCodeAt(i)==kTextChar_InvisibleSeparator
+					|| inpWord.charCodeAt(i)==kTextChar_ZeroWidthNonJoiner
+					|| inpWord.charCodeAt(i)==kTextChar_ZeroWidthJoiner
+					|| inpWord.charCodeAt(i)==kTextChar_ZeroSpaceBreak
+					|| inpWord.charCodeAt(i)==kTextChar_ZeroSpaceNoBreak
+					)
+				continue;
+				
+				tempWord=tempWord+inpWord.charAt(i); 
+			}
+			return tempWord;		
+		}
+		
+		private function replaceIgnoredCharacter(inpWord:String):String
+		{
+			for(var i:int=0; inpWord && i<inpWord.length; i++)
+			{
+				if(inpWord.charCodeAt(i)==kTextChar_RightSingleQuotationMark)
+					inpWord= inpWord.slice(0,i)+String.fromCharCode(kTextChar_Apostrophe)+inpWord.slice(i+1);
+				else if(inpWord.charCodeAt(i)==kTextChar_NoBreakHyphen || inpWord.charCodeAt(i)==kTextChar_UnicodeHyphen)
+					inpWord= inpWord.slice(0,i)+String.fromCharCode(kTextChar_HyphenMinus)+inpWord.slice(i+1);;
+			}
+			return inpWord;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
new file mode 100644
index 0000000..1c68256
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/TextTokenizer.as
@@ -0,0 +1,400 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/* 
+* ToDo: Create ASDoc style comment to generate the API document.
+*/
+
+package com.adobe.linguistics.utils
+{
+	import __AS3__.vec.Vector;
+	
+	import flash.utils.Dictionary;
+	
+    import flash.text.engine.TextBlock;
+    import flash.text.engine.TextElement;
+    import flash.text.engine.ElementFormat;
+
+		
+	/**
+	 * <p>The <code>TextTokenizer</code> class locates the boundaries of words in a 
+	 * block of text.</p>
+	 * 
+	 * Word boundary locations are found according to these general principles:
+	 * <ul>
+	 * 		<li> Be able to tokenize a block of text specified by start and end positions </li> 
+	 * 		<li> Default separator is Unicode white space character. Also break on newlines </li> 
+	 * 		<li> Tokens consist of either words or numbers in which case it may include commas, etc.. </li> 
+	 * 		<li> Apostrophes or hyphens within a word are kept with the word </li> 
+	 * 		<li> Punctuation, spaces and other characters that are not part of a token, are broken out separately </li> 
+	 * </ul>
+	 * <p>In the future versions, this class would also provide a way for the developers to customize the separators used by the tokenizer. </p>
+	 * 
+	 * @playerversion Flash 9.x
+ 	 * @langversion 3.0
+	*/
+	public class TextTokenizer implements ITokenizer
+	{
+		
+
+		private var _textBlock:TextBlock;
+		private var _textHolder:String;
+		private var _startIndex:int;
+		private var _endIndex:int;
+		private var _firstToken:Token;
+		private var _lastToken:Token;
+		
+		private var _ignoredCharactersDict:Dictionary = new Dictionary();
+
+
+		/**
+		 * The tokenizer for a String object.
+		 * This class implements the ITokenizer interface.
+		 * Constructs a new TextTokenizer object to break String to words by creating with a new piece of text. 
+		 * @param textHolder A <code>String</code> object to hold the text which will be processed by this tokenizer.
+		 * @param startIndex A <code>int</code> type input to hold the starting index of input text should be scanned.
+		 * @param endIndex A <code>int</code> type input to hold the ending index of input text should be scanned.
+		 * <span class="hide"> TODO param requestedLocaleIDName The LocaleID name to be used by this TextTokenizer object. </span>
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function TextTokenizer(textHolder:String, startIndex:int=0, endIndex:int=int.MAX_VALUE)//, requestedLocaleIDName:String=null)
+		{
+			//requestedLocaleIDName parameter is useful for potential extension. won't handle it in the first round of implementation.
+			//  same comments for API: requestedLocaleIDName()/actualLocaleIDName()/getAvailableLocaleIDNames()
+            var textElement:TextElement = new TextElement(textHolder, new ElementFormat()); 
+            var textBlock:TextBlock = new TextBlock();
+            textBlock.content = textElement; 
+			
+			/* init a tokenizer object */
+			this._textBlock = textBlock;
+			this._textHolder = textHolder;
+			this._startIndex =  0;
+			this._endIndex = this._textBlock.content.text.length;
+			initDefaultIgnoredCharacters();
+			setStartIndex(startIndex);
+			setEndIndex(endIndex);
+			
+		}
+		
+		private function setStartIndex(value:int):void {
+			if ( value <= 0 ) 
+				this._startIndex = 0;
+			else if ( value >= this._endIndex ) 
+				this._startIndex = this._endIndex;
+			else
+				this._startIndex=value;
+		}
+		
+		// strange behaviour with String.substring() function... need more thinking....
+		private function setEndIndex(value:int):void {
+			if ( value >= this._textBlock.content.text.length ) 
+				this._endIndex = this._textBlock.content.text.length;
+			else if ( value <= this._startIndex ) 
+				this._endIndex = this._startIndex;
+			else
+				this._endIndex = value;
+		}
+
+		private function initDefaultIgnoredCharacters():void {
+			var ignoredCharsArray:Array = [
+				0x002d,
+				0x2010,
+				0x2011,
+				0x0003,
+				0x0007
+			];
+			var ignoredChars:String = "";
+			for ( var i:int=0; i< ignoredCharsArray.length; ++i ) {
+				ignoredChars=ignoredChars+String.fromCharCode(ignoredCharsArray[i]);
+			}
+			this.ignoredCharacters = ignoredChars;
+		}
+
+		private function getNextTokenByIndex( startPos:int ):Token{
+			var resultToken:Token = null;
+			/* calculate first token and return it. */
+			var i:int = (startPos > this._startIndex) ? startPos: this._startIndex;
+			while ( i< this._endIndex ) {
+				var begin:int = i;
+				i = this._textBlock.findNextWordBoundary(begin);
+				var end:int = ( i <= this._endIndex) ? i : this._endIndex;
+				//trace(this._textHolder.substring(begin,end));
+				if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) {
+					resultToken = new Token(begin,end);
+					break;				
+				}
+			}
+			if ( resultToken==null ) resultToken = this.getLastToken();
+			return resultToken;
+		}
+		
+		private function getPreviousTokenByIndex( endPos:int):Token {
+			var resultToken:Token = null;
+			/* calculate first token and return it. */
+			var i:int = (endPos < this._endIndex) ? endPos: this._endIndex;
+			
+			/* special handling for last element in the word, bof */
+			var specialHandling:Boolean = false;
+			if ( i == this._endIndex ) {
+				specialHandling = true;
+				i = this._endIndex -1;
+			}
+			/* special handling for last element in the word, eof */
+			
+			while ( i > this._startIndex ) {
+				var end:int = i;
+				i = this._textBlock.findPreviousWordBoundary(end);
+				var begin:int = ( i > this._startIndex) ? i : this._startIndex;
+				
+				/* special handling for last element in the word, bof */
+				if ( specialHandling ) {
+					end = (this._textBlock.findNextWordBoundary(begin)<this._endIndex) ?this._textBlock.findNextWordBoundary(begin):this._endIndex;
+					specialHandling=false;
+					if ( (end != this._endIndex) && !isSingleSpecialCharacter(this._textHolder.substring(this._endIndex-1,this._endIndex)) ) {
+						begin = this._endIndex-1;
+						i=begin;
+						end = this._endIndex;
+					} 
+				}
+				/* special handling for last element in the word, eof */
+				
+				if ( !isSingleSpecialCharacter( this._textHolder.substring(begin,end) ) ) {
+					resultToken = new Token(begin,end);
+					break;	
+				}
+			}
+			if ( resultToken==null ) resultToken = this.getFirstToken();
+			return resultToken;
+		}
+		
+		private function isExceptionCharacter(word:String):Boolean {
+			if ( word.length != 1 ) return false;
+			if ( this._ignoredCharactersDict[word] == true ) return true;
+			return false;
+		}
+		
+		private function getNextFilteredTokenByIndex(startPos:int):Token {
+			var token:Token = getNextTokenByIndex(startPos);
+			var firstToken:Token = token;
+			var cursor:int=token.last+1;
+			
+			while ( (cursor < this._endIndex) ) {
+				if ( !isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) {
+					break;
+				}else {
+					//another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior...
+					/*bof*/
+					while( cursor < this._endIndex && isExceptionCharacter(this._textHolder.substring(cursor-1,cursor)) ) {
+						cursor++;
+					}
+					cursor--;
+					/*eof*/
+				}
+				token = getNextTokenByIndex(cursor);
+				if ( token.first != cursor ) {
+					token = firstToken;
+					break;
+				}
+				token.first=firstToken.first;
+				firstToken = token;
+				cursor = token.last+1;
+			} 
+			return token;
+		}
+
+		private function getPreviousFilteredTokenByIndex(endPos:int):Token {
+			var token:Token = getPreviousTokenByIndex(endPos);
+			var lastToken:Token = token;
+			var cursor:int=token.first-1;
+			
+			while ( ( cursor > this._startIndex ) ) {
+				if ( !isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) {
+					break;
+				}else {
+					//another request from Harish about handling case abc\\abc abc\.abc case...not 100% sure about the correct behavior...
+					/*bof*/
+					while( cursor > this._startIndex && isExceptionCharacter(this._textHolder.substring(cursor,cursor+1)) ) {
+						cursor--;
+					}
+					cursor++;
+					/*eof*/
+				}
+				token = getPreviousTokenByIndex(cursor);
+				if ( token.last != cursor ) {
+					token = lastToken;
+					break;
+				}
+				token.last=lastToken.last;
+				lastToken = token;
+				cursor = token.first-1;
+			} 
+			return token;
+		}
+
+		private function isSingleSpecialCharacter(word:String):Boolean{
+			if ( word.length != 1 ) return false;
+			if ( word.toLocaleLowerCase() == word.toLocaleUpperCase() ) return true;
+			return false;
+		}
+		
+		/** 
+		 * Set all of ignored separators to this tokenizer class.
+		 * 
+		 * A vector of int containing all of ignored separators code point which are used by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set ignoredSeparators(characters:Vector.<int>):void {
+			if ( characters == null || characters.length==0 ) return;
+			this._ignoredCharactersDict = new Dictionary();
+			for ( var i:int =0;i<characters.length;++i) {
+				this._ignoredCharactersDict[String.fromCharCode(characters[i])]=true;
+			}
+		}
+		
+		/**
+		 * Get all of ignored separators used by this tokenizer class.
+		 * 
+		 * A vector of int containing all of ignored separators code point which are used by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get ignoredSeparators():Vector.<int>{
+			var result:Vector.<int> = new Vector.<int>();
+			for ( var key:String in _ignoredCharactersDict) {
+				result.push(key.charCodeAt(0) );
+			}
+			return result;
+			
+		}
+		
+		private function set ignoredCharacters(value:String ) :void {
+			if( value == null || value == "" ) return;
+			var charArr:Array = value.split("");
+			this._ignoredCharactersDict = new Dictionary();
+			for ( var i:int = 0;i< charArr.length;++i) {
+				this._ignoredCharactersDict[charArr[i]]=true;
+			}
+		}
+		
+		private function get ignoredCharacters():String {
+			var result:String = "";
+			for ( var key:String in _ignoredCharactersDict) {
+				result +=key;
+			}
+			return result;
+		}
+		
+		/**
+		 * The name of the requested locale ID that was passed to the constructor of this TextTokenizer object. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */	/*	
+		public function get requestedLocaleIDName():String {
+			return null;
+		}
+		
+		
+		/**
+		 * The name of the actual locale ID used by this TextTokenizer object. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */	/*	
+		public function get actualLocaleIDName():String {
+			return null;
+		}
+		
+		/**
+		 * Lists all of the locale ID names supported by this class.
+		 * 
+		 * A vector of strings containing all of the locale ID names supported by this class. 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		/*
+		public static function getAvailableLocaleIDNames():Vector.<String>{ return null;}
+*/
+		/**
+		 * Return the first word in the text being scanned. 
+		 * <p> NOTE: In a special case when there are no valid tokens in text, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> firstToken().first </code>equals int.MAX_VALUE and<code> firstToken().last </code>equals int.MAX_VALUE.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getFirstToken():Token {
+			
+			/* return the cached one. */
+			if ( this._firstToken != null )
+				return this._firstToken;
+			
+			/* calculate first token and return it. */
+			//this._firstToken = getNextTokenByIndex(this._startIndex); // without any filter from LS, directly use FTE tokenizer...
+			this._firstToken = getNextFilteredTokenByIndex(this._startIndex);
+
+			return this._firstToken;
+		}
+		
+		/**
+		 * @private
+		 * Return the last word in the text being scanned. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getLastToken():Token {
+			/* return the cached one. */
+			if ( this._lastToken != null )
+				return this._lastToken;
+				
+			/* calculate last token and return it. */
+			this._lastToken = new Token(int.MAX_VALUE,int.MAX_VALUE);
+			return this._lastToken;
+		}
+		
+		/**
+		 * Determine the next word following the current token.  
+		 * 
+		 * <p>Returns the token of the next word.</p><p> NOTE: When there are no more valid tokens, it returns a pseudo token having first and last index set to int.MAX_VALUE. As a result<code> getNextToken().first </code>equals int.MAX_VALUE and<code> getNextToken().last </code>equals int.MAX_VALUE.</p>
+		 * @param token A <code>Token</code> object to be used for determining next word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getNextToken(token:Token):Token {
+			//return getNextTokenByIndex(token.last); // without any filter from LS, directly use FTE tokenizer...
+			return getNextFilteredTokenByIndex(token.last);
+		}
+		
+		/**
+		 * Determine the word preceding the current token.  
+		 * 
+		 * <p>Returns the token of the previous word or<code> getFirstToken </code>object if there is no preceding word.</p>
+		 * @param token A <code>Token</code> object to be used for determining previous word.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function getPreviousToken(token:Token):Token {
+			//return getPreviousTokenByIndex( token.first );// without any filter from LS, directly use FTE tokenizer...
+			return getPreviousFilteredTokenByIndex( token.first )
+		}
+
+	}
+	
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
new file mode 100644
index 0000000..fd93c8e
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeLinguisticUtils/src/com/adobe/linguistics/utils/Token.as
@@ -0,0 +1,95 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/* 
+* ToDo: Create ASDoc style comment to generate the API document.
+*/
+
+package com.adobe.linguistics.utils
+{
+	/**
+	 * A Token is an occurrence of a word in a block of text. It consists of the start and end offset of the word in the block of text.
+	 * The start and end offsets permit applications to re-associate a token with its source text, e.g., to display highlighted misspelled word in 
+	 * a block of text.
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */
+	public class Token
+	{
+		private var _first:uint;
+		private var _last:uint;
+		
+		/**
+		 * The Token class.
+		 * Constructs a Token with first and last offsets. . 
+		 * @param first A <code>int</code> type input to point start offset in the source text.
+		 * @param last A <code>int</code> type input to point end offset in the source text.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function Token(inFirst:int, inLast:int)
+		{
+			_first = inFirst;
+			_last = inLast;
+
+		}
+		
+		/**
+		 * Set the start offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set first(value:int):void {
+			_first=value;
+		}
+		
+		/**
+		 * Return the start offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get first():int
+		{
+			return _first;
+		}
+		
+		/**
+		 * Set the end offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function set last(value:int):void {
+			_last = value;
+		}
+		
+		/**
+		 * Return the end offset in the source text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get last():int
+		{
+			return _last;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
new file mode 100644
index 0000000..330ba4d
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionary.as
@@ -0,0 +1,173 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 __AS3__.vec.Vector;
+	
+	import com.adobe.linguistics.spelling.UserDictionaryInternal;
+	import com.adobe.linguistics.spelling.utils.WordList;
+	
+	import flash.utils.Dictionary;
+
+	/**
+	 * Represents a user dictionary.
+	 *
+	 * <p>This class represents a user dictionary that is used by the <code>SpellingService</code> class. This class itself is an in-memory object
+	 * and doesn't store persistent data. However, developers can import/export a <code>UserDictionary</code> object from/to a vector of String, 
+	 * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage:
+	 *
+	 * <ul>
+	 *	<li>SharedObject, which is used in our SpellingUI class to store words added from the ContextMenu</li>
+	 *	<li>File/FileStream, which is used in our UserDictionaryExample and can be shared across AIR applications</li>
+	 *	<li>Server side storage, for example database so that it can be shared across users</li>
+	 * </ul>
+	 * </p>
+	 * <p>If you are using our SpellingUI class the UserDictionary will be created behind the scene and stored in a SharedObject.</p>
+	 */	 
+	public class UserDictionary
+	{
+		//private var _ud:UserDictionaryInternal;
+		private var _udMap:Dictionary;
+		/**
+		 * @private
+		 */
+		/*
+		public function get internalUserDictionary():UserDictionaryInternal
+		{
+			return _ud;
+		}
+		*/
+		
+		/**
+		 * Constructs a new <code>UserDictionary</code> which can later be added to a <code>SpellingService</code> object.
+		 *
+		 * @param wordList A vector of words (String) to be added as the initial entries of this <code>UserDictionary</code>
+		 * @see UserDictionary.wordList
+		 *
+		 */
+		public function UserDictionary(wordListMap:Array=null)
+		{
+			_udMap= new Dictionary();
+			
+			if(wordListMap)
+			{
+				for (var k:String in wordListMap)
+				{
+					//var wordList:Vector.<Object>= wordListMap[k] as Vector.<Object>;
+					var array:Array = new Array();
+					if (wordListMap[k]/*wordList*/) 
+					{
+						for each (var w:Object in wordListMap[k]/*wordList*/)
+						array.push(w.toString());
+					}
+					_udMap[k] = new UserDictionaryInternal(k, array);
+				}
+				
+			}
+			
+			
+			
+		}
+
+		/**
+		 * Add a word to the user dictionary.
+		 * 
+		 * @param word A word to be added to this <code>UserDictionary</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed, for example if the word is already added.
+		 * @see UserDictionary.removeWord()
+		 * 
+		 */		
+		public function addWord(word:String, language:String = "en_US"):Boolean	
+		{
+			if(_udMap[language]==null)
+				_udMap[language]=new UserDictionaryInternal(language);
+			return _udMap[language].addWord(word);
+		}
+
+		/**
+		 * Removes a word from the user dicitonary.
+		 * 
+		 * @param word A word to be removed from this <code>UserDictionary</code>.
+		 * @return True if the operation was successful, false if the operation was failed, for example if the word doesn't exist in the dictionary.
+		 * @see UserDictionary.addWord()
+		 * 
+		 */		
+		public function removeWord(word:String, language:String = "en_US"):Boolean
+		{
+			
+			return _udMap[language].removeWord(word);
+		}
+
+		/**
+		 * All words in this user dictionary.
+		 *
+		 * @return A vector of String that contains all words in this user dictionary
+		 * 
+		 */		
+		public function getWordList(language:String):WordList
+		{
+			if(language==null || language == "")
+				return null;
+			//var result:Vector.<String> = new Vector.<String>();
+			
+			//for each (var w:String in array)
+			//	result.push(w);
+			var udInternal:UserDictionaryInternal=_udMap[language];
+			
+			return (udInternal? udInternal.wordList as WordList :null);
+		}
+		
+		public function get wordListMap():Array
+		{
+			var result:Array = new Array();
+			for each(var k:Object in _udMap)
+			{
+				var lang:String= k._language;
+				var array:Array= (k.wordList as WordList).toArray();
+				var wordVector:Vector.<String>= new Vector.<String>;
+				if (array) 
+				{
+					for each (var w:String in array)
+					wordVector.push(w);
+				}
+				result[lang] = wordVector;
+				
+			}
+			return result;
+		}
+        
+        public function get wordList():Array
+        {
+            var result:Array = new Array();
+            for each(var k:Object in _udMap)
+            {
+                var lang:String= k._language;
+                var array:Array= (k.wordList as WordList).toArray();
+                var wordVector:Vector.<String>= new Vector.<String>;
+                if (array) 
+                {
+                    for each (var w:String in array)
+                    result.push(w);
+                }
+            }
+            return result;
+        }
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
new file mode 100644
index 0000000..a5225fe
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/UserDictionaryInternal.as
@@ -0,0 +1,120 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils.WordList;
+	
+	/**
+	 * Represents a user dictionary.
+	 *
+	 * <p>This class represents a user dictionary that is used by the <code>SpellChecker</code> class. This class itself is an in-memory object
+	 * and doesn't store persistent data. However, developers can import/export a <code>UserDictionaryInternal</code> object from/to an Array of String, 
+	 * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage:
+	 *
+	 * <ul>
+	 *	<li>SharedObject, which is used in our SpellUI class to store words added from the ContextMenu</li>
+	 *	<li>File/FileStream, which is used in our UserDictionaryInternalExample and can be shared across AIR applications</li>
+	 *	<li>Server side storage, for example database so that it can be shared across users</li>
+	 * </ul>
+	 * </p>
+	 * <p>If you are using our SpellUI class the UserDictionaryInternal will be created behind the scene and stored in a SharedObject.</p>
+	 * @includeExample Examples/Air/UserDictionaryInternalExample/src/UserDictionaryInternalExample.mxml -noswf
+	 * @playerversion Flash 10
+	 * @langversion 3.0
+	 */	 
+	public class UserDictionaryInternal
+	{
+		/**
+		 @private
+		 (This property is for Squiggly Developer use only.)
+		 */
+		public var _wordList:WordList;
+		public var _language:String;
+		
+		/**
+		 * Constructs a new <code>UserDictionaryInternal</code> which can later be added to a <code>SpellChecker</code> object.
+		 *
+		 * @param wordList An array of words (String) to be added as the initial entries of this <code>UserDictionaryInternal</code>
+		 * @see UserDictionaryInternal.wordList
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public function UserDictionaryInternal(language:String, wordList:Array=null)
+		{
+			if(language==null || language=="")
+			{
+				//todo: throw error
+				return;
+			}
+			_language= language;
+			// TODO: exception if has some problem with insert
+			_wordList= new WordList(_language);
+			if (wordList) {
+				for each (var w:String in wordList)
+				_wordList.insert(w); 
+			}
+		}
+		
+		/**
+		 * Add a word to the user dictionary.
+		 * 
+		 * @param word A word to be added to this <code>UserDictionaryInternal</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed.
+		 * @see UserDictionaryInternal.removeWord()
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function addWord(word:String):Boolean	
+		{
+			return _wordList.insert(word);
+		}
+		
+		/**
+		 * Removes a word from the user dicitonary.
+		 * 
+		 * @param word A word to be removed from this <code>UserDictionaryInternal</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed.
+		 * @see UserDictionaryInternal.addWord()
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function removeWord(word:String):Boolean
+		{
+			return _wordList.remove(word);
+		}
+		
+		/**
+		 * List of all words in this user dictionary.
+		 *
+		 * @return An Array of String that contains all words in this user dictionary
+		 * 
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */		
+		public function get wordList():WordList
+		{
+			// TODO: make sure no return by reference
+			return _wordList;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
new file mode 100644
index 0000000..a8a60bc
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as
@@ -0,0 +1,75 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.core
+{
+	import com.adobe.linguistics.spelling.UserDictionary;
+	import com.adobe.linguistics.spelling.utils.WordList;
+	
+	public class UserDictionaryEngine
+	{
+		// Private properties
+		private var _dictionaryList:Array;		// get only
+		private var _userDict:UserDictionary;
+
+		public function UserDictionaryEngine(ud:UserDictionary=null)
+		{
+			_dictionaryList = new Array();
+		}
+		public function addDictionary(userDictionary:UserDictionary):Boolean
+		{
+			if ( (userDictionary == null) ) return false;
+			
+			for ( var i:int = 0;i < _dictionaryList.length; ++i ) {
+				if ( userDictionary == _dictionaryList[i] )
+					return false;
+			} 
+			_dictionaryList.push(userDictionary);
+			return true;
+		}
+
+		public function removeDictionary(userDictionary:UserDictionary):Boolean
+		{
+			
+			for ( var i:int =0; i < _dictionaryList.length; ++i ) {
+				if ( userDictionary == _dictionaryList[i] ) {
+					_dictionaryList.splice(i,1);
+					return true;
+				}
+			}
+			return false;
+		}
+		
+		public function spell( word:String, language:String ) :Boolean {
+			var result:Boolean = false;
+			for ( var i:int =0; (i < _dictionaryList.length) && (!result);++i ) {
+				_userDict = _dictionaryList[i];
+				if ( _userDict ) {
+					var wordList:WordList=_userDict.getWordList(language);
+					if(wordList)
+						result = (wordList.lookup(word) != -1);
+					else
+						result=false;
+				}
+			}
+			return result;
+		}
+
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
new file mode 100644
index 0000000..b405551
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingEngine/src/com/adobe/linguistics/spelling/utils/WordList.as
@@ -0,0 +1,128 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/* 
+* ToDo: Create ASDoc style comment to generate the API document.
+*/
+
+package com.adobe.linguistics.spelling.utils
+{
+	[RemoteClass]
+	public class WordList
+	{
+		private var _words:Array;
+		private var _sorted:Boolean;  // TODO: Shouldn't be always sorted?
+		private var _language:String;
+		
+		public function WordList(language:String, wordsList:Array=null)
+		{
+			if(wordsList!=null) {
+				_words=wordsList;	
+			}else {
+				_words=new Array();
+			}
+			if(language!=null && language!="")
+				_language=language;
+		}
+		
+		public function toArray():Array {
+			return this._words;
+		}
+
+		public function set data(inData:Array):void {
+			this._words = inData;
+		}
+		
+		public function get data():Array {
+			return this._words;
+		}
+		
+		public function insert(value:String):Boolean {
+			if( _words.length==0 ) {
+				_words.push(value)
+				return true;
+			}
+			var low:uint= 0;
+			var high:uint= _words.length-1;
+			var middle:uint= (low+high)/2;
+			while (low<high) {
+				if(_words[middle]<value) {
+					low=middle+1;
+				}else {
+					high=middle;
+				}
+				middle= (low+high)/2;
+			}
+			if( (low <= _words.length-1) && (_words[low]!=value) ) {
+				var pos:uint=_words[low]>value?low:low+1;
+				_words.splice(pos,0,value);
+				return true;
+			}else {
+				return false;
+			}
+			_words.push(value);
+			return true;
+		}
+		
+		public function remove(value:String):Boolean {
+			var pos:int= lookup(value);
+			if( pos!= -1 ) {
+				_words.splice(pos,1);
+				return true;
+			}else {
+				return false;
+			}
+		}
+		
+		//binary search to find the word.
+		public function lookup(value:String):int {
+			if(_words.length==0) {
+				return -1;
+			}
+			var low:uint= 0;
+			var high:uint= _words.length-1;
+			var middle:uint= (low+high)/2;
+			while (low<high) {
+				if(_words[middle]<value) {
+					low=middle+1;
+				}else {
+					high=middle;
+				}
+				middle= (low+high)/2;
+			}
+			if( (low <= _words.length-1) && (_words[low]==value) ) {
+				return low;
+			}else {
+				return -1;
+			}
+			
+		}
+		
+		public function mergeWordLists(list1:WordList,list2:WordList):WordList {
+			return null;
+		}
+
+		public function get language():String
+		{
+			return _language;
+		}
+
+
+	}
+}
\ No newline at end of file

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

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

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

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as b/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
new file mode 100644
index 0000000..629d592
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/SpellingService.as
@@ -0,0 +1,223 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+  
+  
+package com.adobe.linguistics.spelling.framework
+{
+	import com.adobe.linguistics.extensions.HunspellNativeExtension;
+	import com.adobe.linguistics.spelling.UserDictionary;
+	import com.adobe.linguistics.spelling.core.UserDictionaryEngine;
+	
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	/**
+	 * The SpellingService provides spell checking features for the specified language. 
+	 * This class makes use of SpellingConfiguration class to dynamically get the language dictionary location. The dictionaries are then loaded and SpellChecker object
+	 * created based on these dictionaries. 
+	 * @includeExample ../Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml -noswf
+	 * @playerversion Flash 10
+	 * @langversion 3.0.
+	 * 
+	 */
+	public class SpellingService extends EventDispatcher
+	{
+		private var _language:String = null;
+		private const _allLanguage:String= "lang_neutral";
+		private var _udEngine:UserDictionaryEngine = null;
+		private var _userDictionaries:Array = new Array();
+		private var _thirdPatyResourceLocation:String;
+		
+		private var _nativeExtension:HunspellNativeExtension;
+		private var _nativeIsInit:Boolean;				
+		// Static table for caching engines and fixed dictionaries
+		//private static var _engines:Array = new Array();
+	//	private static var _dicts:Array = new Array();
+		private static const HUNSPELL_INIT_FAIL:int= -1
+		private static const RESOURCE_FILES_MISSING:int= -2
+		private static const HUNSPELL_INIT_SUCCESS:int= 1
+			
+		
+		
+		/**
+		 * Constructs a spelling service object.
+		 *
+		 * @param language The language used to create a <code>SpellingService</code>.
+		 */
+		public function SpellingService(language:String)
+		{
+			_language = language;	
+			_thirdPatyResourceLocation="";
+		}
+
+		/**
+		 * Initialize the <code>SpellingService</code>. 
+		 */		
+		public function init():void
+		{
+			_udEngine = new UserDictionaryEngine();
+			//initialize native extension
+			_nativeExtension= new HunspellNativeExtension();
+			//"E:\\P90\\esg\\users\\ugoyal\\nativeLib\\Dictionaries"
+			
+			if(_thirdPatyResourceLocation!="" && ( _nativeExtension.initHunspellObject(_language, _thirdPatyResourceLocation)==HUNSPELL_INIT_SUCCESS ) )
+				_nativeIsInit=true;
+			else
+				_nativeIsInit=false;
+			loadDictComplete(null);//TODO: If performace problems are found use event mechanism in DLL to load ANE.
+		}
+		
+		private function loadDictComplete(e:Event):void
+		{
+
+			dispatchEvent(new Event(Event.COMPLETE));
+		}
+	
+		/**
+		 * Check the spelling of a word.
+		 *
+		 * @param word The word to be checked.
+		 * @return True if the word is correctly spelled, false if it is misspelled.
+		 */		
+		public function checkWord(word:String):Boolean
+		{
+			if(_nativeIsInit)
+			return (  _udEngine.spell(word, _language) || _udEngine.spell(word, _allLanguage)|| _nativeExtension.checkWord(word,_language) );
+			else //return true if the ANE is failed to initialize i.e. stop spell checking without effect working of the Product.
+				return true;
+			//return ((_udEngine.spell(word)) || (_engine.checkWord(word)));
+		}
+
+		/**
+		 * Get the suggestion of a misspelled word. 
+		 *
+		 * @param word The word to be checked.
+		 * @return A vector containing all suggestions for the misspelled word, ordered by similarity to the original word. 
+		 * Note that if a word is already correctly spelled, an empty Vector is returned.
+		 * @internal TODO: get the suggestions from user dicitonaries
+		 */			
+		public function getSuggestions(word:String):Vector.<String>
+		{
+			var resultArray:Array;
+			if (_nativeIsInit)
+				resultArray=_nativeExtension.getSuggestions(word, _language);
+		//	var resultArray:Array;= _engine.getSuggestions(word);
+			
+			var resultVector:Vector.<String> = new Vector.<String>();
+			for each (var i:String in resultArray) {
+				resultVector.push(i);		
+			}
+			
+			return resultVector;
+		}
+		
+		/** 
+		 * Add a <code>UserDictionary</code> to the <code>SpellingService</code>.
+		 * 
+		 * @param userDictionary The UserDictionary to be added.
+		 * @return True if the UserDictionary is added successfully, false if any error occurs. An example error scenario: Trying to add a previously added user dictionary. 
+		 * @see UserDictionary
+		 */
+		public function addUserDictionary(userDictionary:UserDictionary):Boolean
+		{
+			if  (_udEngine.addDictionary(userDictionary) == true)
+			{
+				_userDictionaries.push(userDictionary);
+				return true;
+			} 
+			
+			return false;
+		}
+
+		/** 
+		 * Remove a <code>UserDictionary</code> from the <code>SpellingService</code>.
+		 * 
+		 * @param userDictionary The UserDictionary to be removed.
+		 * @return True if the UserDictionary is removed successfully, false if any error occurs. An example error scenario: Trying to remove a user dictionary that has not been added previously. 
+		 * @see UserDictionary
+		 */		
+		public function removeUserDictionary(userDictionary:UserDictionary):Boolean
+		{
+			if (_udEngine.removeDictionary(userDictionary) == true)
+			{
+				for ( var i:int =0; i < _userDictionaries.length; ++i ) {
+					if ( userDictionary == _userDictionaries[i] ) {
+						_userDictionaries.splice(i,1);
+						return true;
+					}
+				}
+			}
+			
+			return false;
+		}
+		
+		/**
+		 * A <code>Vector</code> of user dictionaries added to this <code>SpellingService</code>.
+		 * 
+		 * @return A <code>Vector</code> of <code>UserDictionary</code> objects.
+		 * @see UserDictionary
+		 */
+		public function get userDictionaries():Vector.<UserDictionary>
+		{	
+			var resultVector:Vector.<UserDictionary> = new Vector.<UserDictionary>;
+			for each (var i:UserDictionary in _userDictionaries) {
+				resultVector.push(i);		
+			}
+			
+			return resultVector;
+		}
+		
+		/**
+		 * This property controls if words in all upper-case should be considered as properly spelled or not.
+		 * 
+		 * <table class="innertable">
+		 *		<tr>
+		 *			<td align="center"><strong><code>ignoreWordWithAllUpperCase</code></strong></td>
+		 *			<td align="center"><strong>&#160;</strong></td>
+		 *			<td align="center"><strong>Description</strong></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>false</code></td>
+		 *			<td>Default</td>
+		 *			<td><p>Words with all characters in upper case are checked against the dictionary for proper spelling.</p>
+		 *				<p>Example: if <code>ignoreWordWithAllUpperCase = false</code>, "MISPEL" will be checked for proper spelling.</p></td>
+		 *		</tr>
+		 *		<tr>
+		 *			<td><code>true</code></td>
+		 *			<td>&#160;</td>
+		 *			<td><p>Any words with all characters in upper case are always considered as properly spelled,
+		 *					no matter whether the word is in the dictionary or not.</p>
+		 *				<p>Example: if <code>ignoreWordWithAllUpperCase = true</code>, "MISPEL" will be considered as properly spelled.</p></td>
+		 *		</tr>
+		 *	</table>
+		 * */
+
+		
+		public function get thirdPatyResourceLocation():String
+		{
+			return _thirdPatyResourceLocation;
+		}
+		
+		public function set thirdPatyResourceLocation(value:String):void
+		{
+			_thirdPatyResourceLocation = value;
+		}
+	}
+}
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/UserDictionaryV.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/UserDictionaryV.as b/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/UserDictionaryV.as
new file mode 100644
index 0000000..a96ba50
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingFramework/src/com/adobe/linguistics/spelling/framework/UserDictionaryV.as
@@ -0,0 +1,113 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+package com.adobe.linguistics.spelling.framework
+{
+	import __AS3__.vec.Vector;
+	
+	import com.adobe.linguistics.spelling.UserDictionary;
+	/**
+	 * Represents a user dictionary.
+	 *
+	 * <p>This class represents a user dictionary that is used by the <code>SpellingService</code> class. This class itself is an in-memory object
+	 * and doesn't store persistent data. However, developers can import/export a <code>UserDictionary</code> object from/to a vector of String, 
+	 * and use other flash classes to keep the data persistent. You may want to consider using one of the following options for permanent storage:
+	 *
+	 * <ul>
+	 *	<li>SharedObject, which is used in our SpellingUI class to store words added from the ContextMenu</li>
+	 *	<li>File/FileStream, which is used in our UserDictionaryExample and can be shared across AIR applications</li>
+	 *	<li>Server side storage, for example database so that it can be shared across users</li>
+	 * </ul>
+	 * </p>
+	 * <p>If you are using our SpellingUI class the UserDictionary will be created behind the scene and stored in a SharedObject.</p>
+	 */	 
+	public class UserDictionaryV
+	{
+		private var _ud:com.adobe.linguistics.spelling.UserDictionary;
+		
+		/**
+		 * @private
+		 */
+		public function get internalUserDictionary():com.adobe.linguistics.spelling.UserDictionary
+		{
+			return _ud;
+		}
+		
+		/**
+		 * Constructs a new <code>UserDictionary</code> which can later be added to a <code>SpellingService</code> object.
+		 *
+		 * @param wordList A vector of words (String) to be added as the initial entries of this <code>UserDictionary</code>
+		 * @see UserDictionary.wordList
+		 *
+		 */
+		public function UserDictionaryV(wordList:Vector.<String>=null)
+		{
+			var array:Array = new Array();
+			if (wordList) {
+				for each (var w:String in wordList)
+					array.push(w);
+			}
+			
+			_ud = new com.adobe.linguistics.spelling.UserDictionary(array);
+		}
+
+		/**
+		 * Add a word to the user dictionary.
+		 * 
+		 * @param word A word to be added to this <code>UserDictionary</code>.
+		 * @return <code>true</code> if the operation is successful. <code>false</code> if the operation is failed, for example if the word is already added.
+		 * @see UserDictionary.removeWord()
+		 * 
+		 */		
+		public function addWord(word:String):Boolean	
+		{
+			return _ud.addWord(word);
+		}
+
+		/**
+		 * Removes a word from the user dicitonary.
+		 * 
+		 * @param word A word to be removed from this <code>UserDictionary</code>.
+		 * @return True if the operation was successful, false if the operation was failed, for example if the word doesn't exist in the dictionary.
+		 * @see UserDictionary.addWord()
+		 * 
+		 */		
+		public function removeWord(word:String):Boolean
+		{
+			return _ud.removeWord(word);
+		}
+
+		/**
+		 * All words in this user dictionary.
+		 *
+		 * @return A vector of String that contains all words in this user dictionary
+		 * 
+		 */		
+		public function get wordList():Vector.<String>
+		{
+			var result:Vector.<String> = new Vector.<String>();
+			var array:Array = _ud.wordList;
+			
+			for each (var w:String in array)
+				result.push(w);
+			
+			return result;
+		}
+	}
+}
\ No newline at end of file


[12/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleUBS.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleUBS.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleUBS.mxml
new file mode 100644
index 0000000..4661bcf
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleUBS.mxml
@@ -0,0 +1,596 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!--<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">	-->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+			   xmlns:s="library://ns.adobe.com/flex/spark" 
+			   xmlns:mx="library://ns.adobe.com/flex/mx" 
+			   xmlns:popup="popup.*" 
+			   minWidth="955" minHeight="600" 
+			   >
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;	
+			/*//------------------------
+			//thread variable
+			private var thread:PseudoThread;
+			//this is a thread function added
+			private function launchThread():void
+			{
+			thread = new PseudoThread(systemManager, enableFeature);
+			thread.addEventListener("threadComplete", threadCompleteHandler);
+			}
+			//a do nothing fucntion
+			private function threadCompleteHandler(event:Event):void
+			{
+			}
+			//--------------------------*/
+			private function enableFeature():void {
+				/*	var str1:String="C:/p4_garuda1890_ugoyal-xp/esg/users/ravi/squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/";
+				var str2:String="AdobeSpellingConfig.xml";
+				//result.text=str1+ta.text;
+				SpellUI.spellingConfigURL =str1+str2;*/
+				SpellUI.enableSpelling(textArea, "en_US");
+			}
+			private function disableFeature() :void {
+				SpellUI.disableSpelling(textArea);
+				
+			}
+			
+			
+			//--------------------------------
+			/*private function startRotation():void //add this above  creationComplete="startRotation() 	
+			{
+			addEventListener("enterFrame", enterFrameHandler);
+			}
+			
+			private function enterFrameHandler(event:Event):void
+			{
+			//trace("enterFrame");
+			rbutton.rotation += 4;<mx:Button id="rbutton" label="Rotating Button"/>	
+			}*/
+			//---------------------------
+		]]>
+	</fx:Script>
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	
+	<mx:TextArea id="textArea" width="30%" height="30%">
+		<mx:text>
+			STARTS
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris dapibus faucibus vehicula. Nulla facilisi. Pellentesque lorem nunc, tempor id molestie et, mollis ut velit. Sed ligula nisl, lobortis vitae ornare quis, euismod placerat purus. Nullam convallis mi sed orci rutrum nec vulputate odio pulvinar. Cras mattis vehicula pulvinar. Cras cursus condimentum pretium. Donec ornare dui nec est hendrerit et posuere nunc facilisis. Mauris libero sem, semper semper laoreet in, sollicitudin eu dolor. Integer justo orci, ultricies et facilisis nec, tincidunt at justo. In tincidunt porttitor diam ut consectetur. Nullam sit amet lorem lacus. Fusce lacus sapien, dapibus vel commodo sit amet, eleifend in orci. Sed consectetur ligula eget purus placerat a accumsan turpis scelerisque. Donec in nibh vitae lacus congue dictum.
+			
+			Etiam at mollis nisl. Mauris in iaculis magna. In vel elit consectetur magna tempus adipiscing vitae eu sapien. Nullam nisl eros, aliquet vitae varius vel, vestibulum fermentum neque. Suspendisse arcu quam, elementum nec tincidunt vel, egestas in lectus. Quisque at purus justo, sed blandit nisi. Sed ac magna felis. Fusce dui risus, placerat sit amet ullamcorper mattis, dapibus eu eros. Nam pharetra egestas condimentum. Vestibulum ac viverra nisi. Maecenas ut libero nunc, eu auctor elit. Curabitur pellentesque facilisis fermentum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin mattis lacus at felis dapibus in condimentum metus sagittis.
+			
+			Morbi vitae turpis sed massa ullamcorper imperdiet vitae vitae nisi. Phasellus sodales lobortis erat, nec sodales massa pulvinar vitae. Quisque pharetra, nulla quis bibendum condimentum, nisi ligula interdum metus, et aliquet enim dolor non magna. In venenatis, mi vel aliquam bibendum, purus tellus malesuada nisl, vel lobortis metus arcu et neque. Donec accumsan dolor vel est venenatis facilisis mattis eget lectus. Morbi nec lorem et metus eleifend semper. Suspendisse mauris dolor, commodo eu euismod sed, mollis id tellus. Nullam volutpat, dolor ac scelerisque porttitor, enim orci vestibulum enim, in dapibus mauris sapien eu est. Nullam luctus sodales lorem, sit amet imperdiet arcu sagittis nec. Nulla sed libero mi, nec luctus arcu. Aliquam nisi velit, tempor sed pulvinar id, ultrices a velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut a venenatis ligula.
+			
+			Nam porta viverra risus quis eleifend. Maecenas imperdiet auctor dui. Vivamus ac lobortis nulla. Sed non pharetra libero. Vivamus facilisis consequat hendrerit. Aliquam mattis eleifend libero non ultrices. Suspendisse sit amet venenatis dolor. Sed euismod euismod tincidunt. Mauris dictum feugiat lectus eget convallis. Aliquam nunc nunc, euismod a interdum a, pretium a diam. Etiam nec libero ante, nec gravida eros. Donec a diam in tellus dignissim suscipit eget ac felis. Nunc sed accumsan risus. Suspendisse ante lorem, facilisis at aliquet quis, mattis nec sem.
+			
+			Ut fringilla gravida nisl, sit amet blandit mi imperdiet et. In hac habitasse platea dictumst. Vivamus eu neque sed enim sollicitudin suscipit. Aliquam suscipit aliquet tortor, nec sodales lacus condimentum vitae. Aenean pharetra velit vel nisl iaculis eget vehicula massa fringilla. Sed ut faucibus lorem. Fusce non eros diam, in auctor quam. Donec vulputate placerat consectetur. Nam vehicula, dui semper porta elementum, lorem libero scelerisque magna, id semper diam sem eget nibh. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam quis risus non diam commodo ullamcorper. In elementum dapibus erat a viverra.
+			
+			Praesent consectetur enim ac enim mollis eu vehicula justo luctus. Nam tristique nisi ultricies dolor pulvinar vulputate. Morbi egestas, mi lobortis feugiat mollis, turpis sem porttitor ante, at porta neque nunc congue purus. In vel quam dolor. Aliquam erat volutpat. Nunc semper tempor ipsum vitae facilisis. Nam eu consectetur elit. In aliquet feugiat tellus. Morbi porta pharetra fringilla. Sed euismod fringilla est, quis malesuada neque dictum vitae. Fusce sed lacus non nisi laoreet iaculis. Aenean fringilla tincidunt est. Nulla eu mi justo, quis semper erat. Nunc id diam vitae dolor viverra placerat vitae eu turpis. Praesent sed nisl quis lectus gravida euismod. Sed eget lacus libero. Proin eleifend pharetra sem vehicula ornare.
+			
+			Ut mi arcu, accumsan quis molestie sit amet, hendrerit sit amet magna. Praesent sodales nisl quis libero lobortis mollis. Mauris lectus ipsum, sodales a tempus eget, congue vel velit. Proin auctor sapien rhoncus lectus iaculis facilisis. Sed orci lacus, feugiat ut bibendum non, molestie quis ipsum. Vivamus et nisl vel eros varius dictum dignissim ut purus. Morbi ut risus et nunc ultricies vehicula vel vitae augue. Curabitur nec velit tellus. Donec dapibus, magna in tincidunt bibendum, neque tellus aliquam nulla, vitae pretium metus orci dignissim libero. Cras eget eros et dolor faucibus pretium quis vel tellus. Quisque ullamcorper bibendum ligula, eu tempor leo eleifend porttitor. Donec nisi enim, tempor vitae tempus vitae, molestie et orci. Proin libero libero, congue at elementum ut, congue in justo. Cras quis enim ac leo sollicitudin vehicula. Fusce sed diam sed neque consectetur dictum ac nec diam.
+			
+			Morbi accumsan porttitor sapien quis porttitor. Duis id quam nisl, sodales elementum lacus. Vestibulum eget quam ac justo pellentesque volutpat. Praesent ut vestibulum odio. Pellentesque eget lobortis velit. Proin congue dignissim tempus. Duis eget justo sit amet risus consectetur suscipit non in nunc. Morbi iaculis luctus egestas. Mauris pretium, mauris ac dapibus aliquam, dolor velit dapibus est, ut semper diam nisi nec eros. Nam mollis diam congue nulla tempus ut euismod felis imperdiet.
+			
+			Maecenas hendrerit interdum enim nec egestas. Mauris in sapien orci, at malesuada mi. Proin faucibus ultricies est, vitae luctus elit condimentum eget. Donec suscipit, lorem sit amet rhoncus faucibus, erat orci sollicitudin tortor, ut placerat dolor metus in dolor. Proin ac mauris et neque rhoncus accumsan. Nunc sodales ultrices velit. In lacinia eleifend pretium. Nullam facilisis egestas libero at volutpat. Morbi aliquet volutpat nibh. Etiam sed nunc tortor, et hendrerit augue. Quisque vitae vulputate ante. Sed bibendum quam a magna rutrum pulvinar.
+			
+			Donec tincidunt nunc id libero dapibus interdum. Nam volutpat ligula et nulla fermentum nec lacinia magna aliquam. Sed id ligula velit, at vestibulum dui. Etiam libero arcu, fringilla non porttitor eget, mattis eu risus. Pellentesque vel velit leo, nec mattis eros. Donec venenatis pellentesque metus ut ultricies. Nullam nec bibendum lorem. Etiam nisi nisl, lobortis ac tempor at, pulvinar aliquam sapien. Quisque nulla turpis, ultrices et euismod in, interdum eu odio. Pellentesque suscipit dui nec sem euismod ac tincidunt libero malesuada. Fusce quis vulputate erat. Suspendisse rutrum purus a nunc commodo scelerisque at a enim. Ut viverra massa ut est tempor et fringilla ligula pharetra.
+			
+			Nam tempus orci vel elit viverra molestie. Suspendisse lobortis ultrices ipsum malesuada lobortis. Duis imperdiet lorem in risus interdum commodo. Nam elementum mollis arcu eget pellentesque. Sed vel lectus et odio imperdiet ultrices. Curabitur eget diam eu arcu fermentum condimentum. Proin elementum laoreet aliquet. Nullam faucibus fringilla tortor. Proin nulla neque, tincidunt sit amet interdum eget, laoreet a ligula. Integer rutrum feugiat convallis. Aenean pharetra mi eu mi porttitor nec interdum turpis sollicitudin. Sed justo urna, posuere sed aliquet a, fringilla in nulla. Vestibulum in nisi ac mi eleifend gravida.
+			
+			Ut quis ornare mauris. Phasellus sapien dolor, fermentum quis volutpat non, sollicitudin a nulla. Donec aliquet eros vel velit lobortis laoreet. Nulla eget felis sit amet nibh placerat dictum. Morbi vestibulum pharetra porta. Phasellus ligula tellus, molestie non vestibulum eget, viverra molestie velit. Morbi pretium elit ut nisl imperdiet ultrices aliquam dui iaculis. Suspendisse id condimentum nisl. In hac habitasse platea dictumst. Donec non purus orci, sed euismod velit. In hac habitasse platea dictumst. Ut ultricies enim et diam elementum porttitor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed pharetra dui semper mi malesuada sit amet interdum dolor dapibus. Cras et neque facilisis diam aliquam ullamcorper at vitae lorem.
+			
+			Nullam lacinia laoreet dolor vitae tincidunt. Mauris volutpat nisi et neque lacinia consequat nec accumsan purus. Vestibulum ac est quis ante commodo vulputate et non turpis. Vivamus sit amet eros ac neque feugiat laoreet et a mi. Aenean ultricies pretium condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut lacus magna, sagittis at tempor in, bibendum at odio. Donec auctor leo nec massa vehicula quis mollis lacus hendrerit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec erat nulla, tristique vel adipiscing a, faucibus id erat. Sed suscipit nunc sit amet dui condimentum fermentum.
+			
+			Etiam condimentum, risus eu ornare vehicula, libero lacus porttitor tortor, et feugiat libero augue condimentum nunc. Nulla facilisi. Aliquam lacinia turpis leo, ut tincidunt metus. Phasellus urna dui, vehicula vitae convallis sed, pharetra eu lorem. Cras accumsan vestibulum cursus. Phasellus congue nisl sapien, sit amet fermentum magna. Cras porta pulvinar libero eu luctus. Nullam sodales suscipit arcu eu malesuada. In aliquet vulputate euismod. Phasellus eu mi turpis, eget bibendum urna. Aenean luctus dolor in nisl adipiscing aliquam. Donec in tempor diam. Nam tristique odio nec ipsum semper interdum sit amet aliquet magna. Sed hendrerit, tortor eget faucibus facilisis, diam nisl dignissim nisl, a bibendum nisl dui sit amet lacus. Vestibulum fermentum leo in elit consequat a viverra tellus accumsan. Cras a condimentum mauris. Aliquam quis arcu tellus. Integer dictum sodales dui, a fringilla eros porta placerat. Vestibulum feugiat, odio a cursus aliquet, erat nisl volutpat odio,
  blandit sodales turpis est nec purus. Nullam tincidunt mi non odio sagittis nec facilisis velit porttitor.
+			
+			In pulvinar mi sed ligula imperdiet quis sollicitudin nisi dignissim. Fusce at sodales massa. Phasellus vulputate nibh at justo mattis porttitor gravida augue faucibus. Fusce sit amet quam risus, vel malesuada risus. Aliquam gravida venenatis libero quis congue. In nec ipsum id mauris pretium pharetra. Duis tincidunt hendrerit sollicitudin. Cras condimentum diam et enim facilisis lacinia. Donec posuere rhoncus ante, eu ullamcorper est commodo vel. Sed tellus lectus, congue ut suscipit sed, ultricies nec nulla. Cras malesuada dolor et erat tincidunt dignissim. Quisque eu turpis est, a consectetur orci. Pellentesque neque orci, tristique sit amet volutpat ac, tempus eget urna. Nunc pharetra sapien eget lacus sagittis venenatis. Donec ac leo in erat ornare bibendum. Suspendisse vel dui erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+			
+			Quisque eget turpis dui, vel semper massa. Sed vel dapibus dui. Etiam non sollicitudin orci. Vivamus lectus lectus, iaculis quis molestie id, euismod a nisl. Fusce malesuada scelerisque ligula, nec molestie metus adipiscing quis. Curabitur laoreet lectus vitae eros sagittis rutrum. Phasellus leo ante, aliquet sed porttitor et, sollicitudin vel ligula. Cras bibendum lectus aliquet dui dapibus consequat. Vestibulum gravida lorem sit amet augue tincidunt ac eleifend leo mollis. Quisque id fringilla lectus. Aenean ac felis at dolor consequat porta. Nulla feugiat sem vel justo eleifend id dignissim dui auctor. Aliquam hendrerit vulputate lorem, ut cursus orci placerat at. Praesent eget est erat. Morbi a lorem tortor.
+			
+			Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In hac habitasse platea dictumst. Quisque dictum, enim nec adipiscing accumsan, eros justo aliquet lacus, at dignissim nulla lectus eu justo. Cras auctor luctus purus vitae eleifend. Cras at est eu odio rutrum sollicitudin. Aenean scelerisque volutpat risus sit amet accumsan. Sed eget orci dui. Vestibulum est augue, malesuada eu venenatis tristique, lobortis eu sapien. Vivamus eget sapien non urna iaculis sodales ac a neque. Praesent accumsan purus et nisl hendrerit non condimentum erat varius. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras non purus ac ante faucibus ullamcorper. Mauris blandit pretium nulla, vitae imperdiet quam condimentum nec. Sed mattis urna id felis bibendum dignissim. Maecenas in mi at tellus lobortis lobortis. Vestibulum varius, erat vitae viverra convallis, nisi purus volutpat nisi, et tincidunt lectus enim et libero. Donec
  mattis auctor porta. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+			
+			Proin ornare ipsum eu lacus adipiscing varius. Pellentesque laoreet fermentum tellus, quis dapibus sapien mattis vitae. Maecenas suscipit tempor interdum. Maecenas ut eleifend urna. Phasellus ut auctor sem. Fusce ligula mauris, fermentum et vestibulum et, lacinia a lacus. In vulputate blandit purus nec sollicitudin. Duis tincidunt, turpis vitae faucibus dictum, mauris justo aliquet felis, eu suscipit ipsum lorem vitae metus. Nam commodo tincidunt sagittis. Praesent sit amet neque sed diam convallis blandit. Donec porttitor varius lacus, eget ultricies sem varius sed. Nullam eget risus nec turpis tincidunt convallis id eu mi.
+			
+			Integer non augue orci, non venenatis ligula. Vivamus rutrum purus id neque vehicula tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. Maecenas aliquet facilisis enim. Curabitur commodo egestas nisl eget ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut feugiat, arcu quis cursus vehicula, lorem dolor viverra mi, ac gravida elit lorem at est. In ac ligula egestas tortor consectetur malesuada a cursus nisi. Aenean quis velit augue. Nunc justo diam, iaculis in consequat non, fringilla ac ipsum. Nunc sit amet lacus lectus. In est augue, mollis ullamcorper scelerisque ut, vulputate at massa. Cras eu felis ut dolor auctor porttitor. Aliquam eu risus ut arcu pulvinar lobortis vitae non nibh.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris luctus consequat arcu, viverra eleifend libero vulputate sed. Vivamus consequat arcu pharetra erat bibendum ac suscipit nibh ornare. In vel sapien quis ipsum eleifend gravida id vitae est. Phasellus quis mi odio. Nunc rhoncus, tortor vitae feugiat vehicula, diam diam tempus diam, vel iaculis orci dui id lectus. Morbi rutrum tempus sodales. In nisi turpis, fringilla lobortis fermentum vel, tincidunt eget massa. Nullam facilisis tortor eu nulla pharetra nec malesuada dui sagittis. Quisque elementum vulputate orci ac luctus. Morbi et justo ipsum, eget consequat mi.
+			
+			Integer placerat purus elementum augue ultrices pharetra. Maecenas at diam purus, nec fermentum urna. Praesent ut commodo diam. Suspendisse potenti. Aenean eu lectus accumsan metus varius rhoncus dictum quis purus. Morbi vitae turpis elit, ut euismod justo. Sed sollicitudin malesuada risus, et iaculis lectus aliquet sed. Quisque tellus sem, aliquam et mattis ut, condimentum mattis nisl. Fusce sit amet lorem et lectus scelerisque placerat. Quisque et magna purus. Nullam quis sapien nisi. Integer in ligula vel magna vulputate semper eu nec velit. Duis sollicitudin vestibulum mauris quis malesuada. Praesent luctus sapien et felis convallis eu egestas erat consequat. Nulla tincidunt sagittis euismod. Nunc laoreet odio sollicitudin tortor mattis rhoncus. Curabitur lacinia, lorem nec tempus fringilla, dolor magna tincidunt eros, eu interdum turpis lorem id arcu.
+			
+			Pellentesque pellentesque lorem quis sem volutpat luctus. Proin malesuada nunc sed mi fringilla blandit sit amet ut nibh. Nulla vestibulum dolor ac leo venenatis in condimentum sem varius. Cras nec mattis ipsum. Nulla id libero tellus, ac rutrum elit. Duis eget orci lectus, eget pulvinar justo. Ut ornare erat vel nisl ornare id rutrum velit aliquet. Mauris dapibus commodo tempus. Donec tempus eleifend urna eu imperdiet. Fusce aliquam leo in ipsum egestas ac sollicitudin arcu pharetra. Proin elementum gravida condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fringilla lacinia dolor quis cursus. Sed euismod lorem malesuada libero porttitor pellentesque. Nulla facilisi. Proin mattis eros convallis nisi vulputate in molestie ipsum aliquet. Proin a eros eu sapien faucibus condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis id nibh magna. Proin congue, enim vel imperdiet rutrum, l
 eo augue aliquam turpis, sed scelerisque dolor leo et elit.
+			
+			In vitae magna eget velit condimentum vestibulum. Proin sapien purus, elementum et tincidunt sed, interdum eu orci. Vivamus eget sapien sit amet tellus vulputate euismod eget non ante. Duis consequat urna at quam pharetra vel scelerisque lectus cursus. Aenean varius, sem a venenatis vulputate, ante arcu sodales nulla, id mollis nulla lacus quis sapien. Fusce egestas turpis risus, ut feugiat ante. Fusce pretium diam quis sapien scelerisque consectetur. Cras at ante id risus aliquet cursus quis semper enim. Duis non turpis eu metus pretium interdum. Duis leo sem, elementum ut accumsan sit amet, facilisis eget arcu. Phasellus lacus velit, bibendum in porta eget, aliquam ac felis. Quisque neque eros, scelerisque id semper et, sodales sit amet risus. Aliquam ac tellus eget lacus dictum pretium nec sit amet libero. Maecenas nec nibh lectus, a dignissim leo. Quisque congue sem a risus gravida at congue lectus pellentesque.
+			
+			Nulla leo nulla, sagittis ac interdum ut, faucibus in est. Fusce imperdiet mauris nec lorem luctus sit amet commodo tortor pellentesque. Maecenas lacinia metus ut erat hendrerit ac ultrices purus sagittis. Sed elementum, risus ut elementum molestie, magna felis viverra ipsum, vel lobortis tellus libero id justo. Duis eget sapien convallis sem bibendum scelerisque vel tempor mauris. Etiam ut lorem ipsum, ac gravida lectus. Morbi aliquam, orci non ullamcorper auctor, elit lacus condimentum odio, sit amet lacinia eros ipsum at eros. Vestibulum dictum eros sapien, sed imperdiet sem. Etiam id enim leo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla leo magna, suscipit quis lobortis id, egestas id purus. Maecenas eu est turpis, et euismod mi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ligula nibh, iaculis eu porta eget, euismod in turpis. Sed turpis velit, porta ac scelerisq
 ue ac, accumsan vel nulla. Ut nec ante posuere lacus tristique ornare. Quisque viverra rutrum commodo.
+			
+			Sed magna diam, ultricies ultricies tincidunt sit amet, ultricies quis felis. Suspendisse ac mauris mi, non pretium erat. Sed faucibus aliquet metus sit amet mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lorem lacus, convallis porta fermentum ut, adipiscing quis quam. Maecenas bibendum dapibus eros in convallis. Suspendisse ut odio augue. Morbi mattis, quam a posuere placerat, leo dui cursus felis, ac mollis purus odio sed quam. Mauris elementum aliquet mauris, commodo tristique tellus semper quis. Quisque tellus justo, dapibus eget pretium id, viverra non turpis. Pellentesque luctus pulvinar dignissim.
+			
+			Proin molestie rutrum est, ac placerat arcu placerat et. Sed rhoncus sollicitudin augue, id vulputate nunc iaculis id. Vivamus consectetur placerat mi, vehicula faucibus ipsum placerat ut. In quis dui ligula, non lobortis tortor. Nunc sit amet quam sem, at faucibus neque. Sed scelerisque lacinia aliquam. Nunc quis dolor sit amet velit convallis eleifend a interdum mi. Sed tellus est, rutrum sit amet euismod non, sollicitudin sed lorem. Cras id aliquam est. Curabitur velit neque, hendrerit a volutpat sed, iaculis vitae massa. Duis non est vel ligula hendrerit pellentesque et vitae velit. Ut sed felis metus, quis convallis eros. Aliquam sit amet nunc at justo egestas aliquam. Morbi ut ante eros, in pretium metus. Sed fermentum orci sit amet mauris lobortis tincidunt et eget arcu. Morbi mattis, elit vel dictum sollicitudin, lectus libero ultrices nunc, sed dapibus urna felis quis orci. Donec eu urna at nisi tempus pretium at ac dui. In suscipit elementum congue.
+			
+			Pellentesque lorem purus, dignissim eget congue sed, gravida id orci. Aenean ligula lacus, accumsan vitae pulvinar ac, sollicitudin vel augue. Sed nec ante vel ante dignissim cursus. Morbi eleifend, nunc nec luctus pretium, eros nulla auctor mi, at commodo magna mi in lectus. Fusce et nisl tellus, id ullamcorper nisl. Vestibulum iaculis felis non sem bibendum sed feugiat lorem ultrices. In mauris nisl, eleifend at fringilla vitae, ullamcorper ut neque. Vestibulum eget turpis ac enim porta porttitor tincidunt sit amet erat. Nullam accumsan risus neque, et euismod leo. Nam nibh quam, congue eget blandit in, tristique quis mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at nibh justo, eleifend hendrerit enim.
+			
+			Duis at porta lectus. Duis placerat imperdiet aliquam. Vestibulum tortor augue, aliquam nec venenatis in, ultricies sit amet justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus nec orci vel ligula eleifend ultrices quis euismod diam. Suspendisse eleifend tincidunt nisl non aliquam. Donec sagittis odio eu sapien ultrices mattis. Nulla sagittis pulvinar est, rhoncus mollis dui gravida eget. Cras et nisi ante, in luctus leo. Phasellus a porttitor metus. Nam tortor enim, porta cursus tempor vel, rhoncus ut tortor. Morbi enim velit, dictum vel pulvinar quis, interdum nec tortor. Vivamus et justo ligula, nec commodo lorem. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur ligula mi, eleifend a pellentesque id, adipiscing id metus. Nunc vel dui et enim porttitor sollicitudin. In pretium ultrices congue. Donec malesuada convallis convallis. Aliquam quis risus lorem.
+			
+			In est lectus, rutrum vel convallis sed, egestas vitae leo. Donec augue odio, ultricies in consequat non, scelerisque nec nisi. Suspendisse potenti. Pellentesque ullamcorper arcu vel magna iaculis auctor. Pellentesque blandit accumsan lorem sagittis accumsan. Donec dignissim porttitor urna, non blandit magna pulvinar in. Donec tristique lacus sit amet nulla vehicula iaculis. Vestibulum pharetra odio lorem, at volutpat tellus. Fusce quis lorem odio. Sed ornare purus id sem elementum egestas ac sed nunc. Quisque convallis, augue vitae porta lobortis, nibh magna condimentum massa, id tincidunt magna magna ac odio. Donec quam nisi, bibendum et mollis at, molestie vitae mi. Suspendisse potenti.
+			
+			Nullam dolor nunc, condimentum ut vehicula sollicitudin, lacinia sit amet sapien. Nullam et enim id tortor suscipit ultrices. Nulla ut lorem leo, vel sodales leo. Donec erat nulla, sollicitudin eu varius sed, consectetur vel risus. Sed vehicula pulvinar lorem, at scelerisque dolor iaculis vitae. In purus ante, malesuada vitae euismod et, dictum sed ipsum. Ut nibh sapien, tristique sit amet sagittis eget, adipiscing at dolor. Nunc sit amet risus porta ligula rutrum commodo a a diam. Duis adipiscing enim ipsum, sit amet auctor diam. Sed vel tellus et sapien commodo molestie. Sed id risus consectetur lectus malesuada lacinia. Sed a aliquam enim. Fusce venenatis leo faucibus magna tempus sit amet sodales nisi pharetra. Vestibulum velit justo, pulvinar nec euismod facilisis, aliquet quis eros. In erat mauris, cursus a adipiscing non, semper eu erat. Donec id est mauris. Fusce fermentum fringilla vehicula. Mauris malesuada ligula placerat lorem tristique eu dignissim est feugiat.
+			
+			Vestibulum commodo elit ut nisi iaculis vehicula. Quisque bibendum, eros ut cursus dictum, risus mauris volutpat est, sed mollis metus justo et enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed et eros eget sapien aliquam cursus vel et erat. In commodo nunc sodales nibh sagittis vehicula. Nam dapibus justo sed nulla pellentesque faucibus. Nulla posuere ullamcorper libero, in porttitor diam vulputate vel. Sed vel dolor est. Proin sit amet convallis dui. Ut et libero quis sem vulputate rutrum eget ac dolor. Morbi eget massa dolor. In hac habitasse platea dictumst. Pellentesque consectetur arcu quis lacus varius bibendum. Donec placerat fringilla nulla vel semper.
+			
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce mollis nisi pharetra massa rhoncus tempus. Sed ac mauris ut sapien hendrerit dignissim eu a urna. Curabitur pretium fringilla orci ut dictum. In vulputate urna in diam scelerisque lobortis. Sed in dolor sit amet erat interdum commodo. Etiam dignissim consectetur nibh sit amet lobortis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut laoreet nisl a nunc suscipit et luctus est bibendum. Morbi in elit elit. Donec vitae diam enim. Praesent arcu justo, faucibus at varius vitae, porta laoreet elit. Donec eleifend mattis semper. Morbi tempus neque et nisl rhoncus adipiscing. Etiam venenatis consectetur nisl, eu congue velit lacinia sit amet. Nunc venenatis lacus a mi aliquet at volutpat elit semper. Pellentesque luctus laoreet sapien, ac tempus elit dignissim id.
+			
+			Aliquam cursus mattis bibendum. Praesent rhoncus augue sed ligula iaculis dapibus. Fusce facilisis eleifend leo ut dignissim. Morbi gravida luctus velit sit amet suscipit. In justo turpis, condimentum eget pharetra ac, consectetur vitae nisi. Suspendisse potenti. Proin euismod ante vitae lorem luctus tempus. Suspendisse sodales nisi in mauris elementum congue a dictum ipsum. Duis a mattis dui. Nulla ac ipsum id purus hendrerit pellentesque rhoncus quis odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at mauris egestas mi tristique mattis. Vivamus ac risus vitae ante congue porta. Suspendisse ut lacus dolor. Suspendisse quis quam metus, et porta urna. Nulla malesuada porta lacus at dictum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
+			
+			Donec et dignissim ligula. Phasellus vitae interdum mauris. Curabitur sit amet lacus sed magna consequat dictum. Phasellus laoreet enim sit amet metus pharetra pulvinar ut aliquam nisl. Praesent et metus nisl. Nulla nec elit nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer commodo luctus commodo. Fusce sed turpis facilisis urna laoreet semper. Pellentesque quis tellus ut augue commodo venenatis euismod a nulla. Integer tempus lacinia urna non pharetra. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus nec eros arcu. Aenean nec laoreet diam. In eget arcu hendrerit ligula fermentum interdum eu sagittis massa. Cras dapibus magna quis diam venenatis eget porttitor lacus ornare.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris dapibus faucibus vehicula. Nulla facilisi. Pellentesque lorem nunc, tempor id molestie et, mollis ut velit. Sed ligula nisl, lobortis vitae ornare quis, euismod placerat purus. Nullam convallis mi sed orci rutrum nec vulputate odio pulvinar. Cras mattis vehicula pulvinar. Cras cursus condimentum pretium. Donec ornare dui nec est hendrerit et posuere nunc facilisis. Mauris libero sem, semper semper laoreet in, sollicitudin eu dolor. Integer justo orci, ultricies et facilisis nec, tincidunt at justo. In tincidunt porttitor diam ut consectetur. Nullam sit amet lorem lacus. Fusce lacus sapien, dapibus vel commodo sit amet, eleifend in orci. Sed consectetur ligula eget purus placerat a accumsan turpis scelerisque. Donec in nibh vitae lacus congue dictum.
+			
+			Etiam at mollis nisl. Mauris in iaculis magna. In vel elit consectetur magna tempus adipiscing vitae eu sapien. Nullam nisl eros, aliquet vitae varius vel, vestibulum fermentum neque. Suspendisse arcu quam, elementum nec tincidunt vel, egestas in lectus. Quisque at purus justo, sed blandit nisi. Sed ac magna felis. Fusce dui risus, placerat sit amet ullamcorper mattis, dapibus eu eros. Nam pharetra egestas condimentum. Vestibulum ac viverra nisi. Maecenas ut libero nunc, eu auctor elit. Curabitur pellentesque facilisis fermentum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin mattis lacus at felis dapibus in condimentum metus sagittis.
+			
+			Morbi vitae turpis sed massa ullamcorper imperdiet vitae vitae nisi. Phasellus sodales lobortis erat, nec sodales massa pulvinar vitae. Quisque pharetra, nulla quis bibendum condimentum, nisi ligula interdum metus, et aliquet enim dolor non magna. In venenatis, mi vel aliquam bibendum, purus tellus malesuada nisl, vel lobortis metus arcu et neque. Donec accumsan dolor vel est venenatis facilisis mattis eget lectus. Morbi nec lorem et metus eleifend semper. Suspendisse mauris dolor, commodo eu euismod sed, mollis id tellus. Nullam volutpat, dolor ac scelerisque porttitor, enim orci vestibulum enim, in dapibus mauris sapien eu est. Nullam luctus sodales lorem, sit amet imperdiet arcu sagittis nec. Nulla sed libero mi, nec luctus arcu. Aliquam nisi velit, tempor sed pulvinar id, ultrices a velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut a venenatis ligula.
+			
+			Nam porta viverra risus quis eleifend. Maecenas imperdiet auctor dui. Vivamus ac lobortis nulla. Sed non pharetra libero. Vivamus facilisis consequat hendrerit. Aliquam mattis eleifend libero non ultrices. Suspendisse sit amet venenatis dolor. Sed euismod euismod tincidunt. Mauris dictum feugiat lectus eget convallis. Aliquam nunc nunc, euismod a interdum a, pretium a diam. Etiam nec libero ante, nec gravida eros. Donec a diam in tellus dignissim suscipit eget ac felis. Nunc sed accumsan risus. Suspendisse ante lorem, facilisis at aliquet quis, mattis nec sem.
+			
+			Ut fringilla gravida nisl, sit amet blandit mi imperdiet et. In hac habitasse platea dictumst. Vivamus eu neque sed enim sollicitudin suscipit. Aliquam suscipit aliquet tortor, nec sodales lacus condimentum vitae. Aenean pharetra velit vel nisl iaculis eget vehicula massa fringilla. Sed ut faucibus lorem. Fusce non eros diam, in auctor quam. Donec vulputate placerat consectetur. Nam vehicula, dui semper porta elementum, lorem libero scelerisque magna, id semper diam sem eget nibh. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam quis risus non diam commodo ullamcorper. In elementum dapibus erat a viverra.
+			
+			Praesent consectetur enim ac enim mollis eu vehicula justo luctus. Nam tristique nisi ultricies dolor pulvinar vulputate. Morbi egestas, mi lobortis feugiat mollis, turpis sem porttitor ante, at porta neque nunc congue purus. In vel quam dolor. Aliquam erat volutpat. Nunc semper tempor ipsum vitae facilisis. Nam eu consectetur elit. In aliquet feugiat tellus. Morbi porta pharetra fringilla. Sed euismod fringilla est, quis malesuada neque dictum vitae. Fusce sed lacus non nisi laoreet iaculis. Aenean fringilla tincidunt est. Nulla eu mi justo, quis semper erat. Nunc id diam vitae dolor viverra placerat vitae eu turpis. Praesent sed nisl quis lectus gravida euismod. Sed eget lacus libero. Proin eleifend pharetra sem vehicula ornare.
+			
+			Ut mi arcu, accumsan quis molestie sit amet, hendrerit sit amet magna. Praesent sodales nisl quis libero lobortis mollis. Mauris lectus ipsum, sodales a tempus eget, congue vel velit. Proin auctor sapien rhoncus lectus iaculis facilisis. Sed orci lacus, feugiat ut bibendum non, molestie quis ipsum. Vivamus et nisl vel eros varius dictum dignissim ut purus. Morbi ut risus et nunc ultricies vehicula vel vitae augue. Curabitur nec velit tellus. Donec dapibus, magna in tincidunt bibendum, neque tellus aliquam nulla, vitae pretium metus orci dignissim libero. Cras eget eros et dolor faucibus pretium quis vel tellus. Quisque ullamcorper bibendum ligula, eu tempor leo eleifend porttitor. Donec nisi enim, tempor vitae tempus vitae, molestie et orci. Proin libero libero, congue at elementum ut, congue in justo. Cras quis enim ac leo sollicitudin vehicula. Fusce sed diam sed neque consectetur dictum ac nec diam.
+			
+			Morbi accumsan porttitor sapien quis porttitor. Duis id quam nisl, sodales elementum lacus. Vestibulum eget quam ac justo pellentesque volutpat. Praesent ut vestibulum odio. Pellentesque eget lobortis velit. Proin congue dignissim tempus. Duis eget justo sit amet risus consectetur suscipit non in nunc. Morbi iaculis luctus egestas. Mauris pretium, mauris ac dapibus aliquam, dolor velit dapibus est, ut semper diam nisi nec eros. Nam mollis diam congue nulla tempus ut euismod felis imperdiet.
+			
+			Maecenas hendrerit interdum enim nec egestas. Mauris in sapien orci, at malesuada mi. Proin faucibus ultricies est, vitae luctus elit condimentum eget. Donec suscipit, lorem sit amet rhoncus faucibus, erat orci sollicitudin tortor, ut placerat dolor metus in dolor. Proin ac mauris et neque rhoncus accumsan. Nunc sodales ultrices velit. In lacinia eleifend pretium. Nullam facilisis egestas libero at volutpat. Morbi aliquet volutpat nibh. Etiam sed nunc tortor, et hendrerit augue. Quisque vitae vulputate ante. Sed bibendum quam a magna rutrum pulvinar.
+			
+			Donec tincidunt nunc id libero dapibus interdum. Nam volutpat ligula et nulla fermentum nec lacinia magna aliquam. Sed id ligula velit, at vestibulum dui. Etiam libero arcu, fringilla non porttitor eget, mattis eu risus. Pellentesque vel velit leo, nec mattis eros. Donec venenatis pellentesque metus ut ultricies. Nullam nec bibendum lorem. Etiam nisi nisl, lobortis ac tempor at, pulvinar aliquam sapien. Quisque nulla turpis, ultrices et euismod in, interdum eu odio. Pellentesque suscipit dui nec sem euismod ac tincidunt libero malesuada. Fusce quis vulputate erat. Suspendisse rutrum purus a nunc commodo scelerisque at a enim. Ut viverra massa ut est tempor et fringilla ligula pharetra.
+			
+			Nam tempus orci vel elit viverra molestie. Suspendisse lobortis ultrices ipsum malesuada lobortis. Duis imperdiet lorem in risus interdum commodo. Nam elementum mollis arcu eget pellentesque. Sed vel lectus et odio imperdiet ultrices. Curabitur eget diam eu arcu fermentum condimentum. Proin elementum laoreet aliquet. Nullam faucibus fringilla tortor. Proin nulla neque, tincidunt sit amet interdum eget, laoreet a ligula. Integer rutrum feugiat convallis. Aenean pharetra mi eu mi porttitor nec interdum turpis sollicitudin. Sed justo urna, posuere sed aliquet a, fringilla in nulla. Vestibulum in nisi ac mi eleifend gravida.
+			
+			Ut quis ornare mauris. Phasellus sapien dolor, fermentum quis volutpat non, sollicitudin a nulla. Donec aliquet eros vel velit lobortis laoreet. Nulla eget felis sit amet nibh placerat dictum. Morbi vestibulum pharetra porta. Phasellus ligula tellus, molestie non vestibulum eget, viverra molestie velit. Morbi pretium elit ut nisl imperdiet ultrices aliquam dui iaculis. Suspendisse id condimentum nisl. In hac habitasse platea dictumst. Donec non purus orci, sed euismod velit. In hac habitasse platea dictumst. Ut ultricies enim et diam elementum porttitor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed pharetra dui semper mi malesuada sit amet interdum dolor dapibus. Cras et neque facilisis diam aliquam ullamcorper at vitae lorem.
+			
+			Nullam lacinia laoreet dolor vitae tincidunt. Mauris volutpat nisi et neque lacinia consequat nec accumsan purus. Vestibulum ac est quis ante commodo vulputate et non turpis. Vivamus sit amet eros ac neque feugiat laoreet et a mi. Aenean ultricies pretium condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut lacus magna, sagittis at tempor in, bibendum at odio. Donec auctor leo nec massa vehicula quis mollis lacus hendrerit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec erat nulla, tristique vel adipiscing a, faucibus id erat. Sed suscipit nunc sit amet dui condimentum fermentum.
+			
+			Etiam condimentum, risus eu ornare vehicula, libero lacus porttitor tortor, et feugiat libero augue condimentum nunc. Nulla facilisi. Aliquam lacinia turpis leo, ut tincidunt metus. Phasellus urna dui, vehicula vitae convallis sed, pharetra eu lorem. Cras accumsan vestibulum cursus. Phasellus congue nisl sapien, sit amet fermentum magna. Cras porta pulvinar libero eu luctus. Nullam sodales suscipit arcu eu malesuada. In aliquet vulputate euismod. Phasellus eu mi turpis, eget bibendum urna. Aenean luctus dolor in nisl adipiscing aliquam. Donec in tempor diam. Nam tristique odio nec ipsum semper interdum sit amet aliquet magna. Sed hendrerit, tortor eget faucibus facilisis, diam nisl dignissim nisl, a bibendum nisl dui sit amet lacus. Vestibulum fermentum leo in elit consequat a viverra tellus accumsan. Cras a condimentum mauris. Aliquam quis arcu tellus. Integer dictum sodales dui, a fringilla eros porta placerat. Vestibulum feugiat, odio a cursus aliquet, erat nisl volutpat odio,
  blandit sodales turpis est nec purus. Nullam tincidunt mi non odio sagittis nec facilisis velit porttitor.
+			
+			In pulvinar mi sed ligula imperdiet quis sollicitudin nisi dignissim. Fusce at sodales massa. Phasellus vulputate nibh at justo mattis porttitor gravida augue faucibus. Fusce sit amet quam risus, vel malesuada risus. Aliquam gravida venenatis libero quis congue. In nec ipsum id mauris pretium pharetra. Duis tincidunt hendrerit sollicitudin. Cras condimentum diam et enim facilisis lacinia. Donec posuere rhoncus ante, eu ullamcorper est commodo vel. Sed tellus lectus, congue ut suscipit sed, ultricies nec nulla. Cras malesuada dolor et erat tincidunt dignissim. Quisque eu turpis est, a consectetur orci. Pellentesque neque orci, tristique sit amet volutpat ac, tempus eget urna. Nunc pharetra sapien eget lacus sagittis venenatis. Donec ac leo in erat ornare bibendum. Suspendisse vel dui erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+			
+			Quisque eget turpis dui, vel semper massa. Sed vel dapibus dui. Etiam non sollicitudin orci. Vivamus lectus lectus, iaculis quis molestie id, euismod a nisl. Fusce malesuada scelerisque ligula, nec molestie metus adipiscing quis. Curabitur laoreet lectus vitae eros sagittis rutrum. Phasellus leo ante, aliquet sed porttitor et, sollicitudin vel ligula. Cras bibendum lectus aliquet dui dapibus consequat. Vestibulum gravida lorem sit amet augue tincidunt ac eleifend leo mollis. Quisque id fringilla lectus. Aenean ac felis at dolor consequat porta. Nulla feugiat sem vel justo eleifend id dignissim dui auctor. Aliquam hendrerit vulputate lorem, ut cursus orci placerat at. Praesent eget est erat. Morbi a lorem tortor.
+			
+			Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In hac habitasse platea dictumst. Quisque dictum, enim nec adipiscing accumsan, eros justo aliquet lacus, at dignissim nulla lectus eu justo. Cras auctor luctus purus vitae eleifend. Cras at est eu odio rutrum sollicitudin. Aenean scelerisque volutpat risus sit amet accumsan. Sed eget orci dui. Vestibulum est augue, malesuada eu venenatis tristique, lobortis eu sapien. Vivamus eget sapien non urna iaculis sodales ac a neque. Praesent accumsan purus et nisl hendrerit non condimentum erat varius. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras non purus ac ante faucibus ullamcorper. Mauris blandit pretium nulla, vitae imperdiet quam condimentum nec. Sed mattis urna id felis bibendum dignissim. Maecenas in mi at tellus lobortis lobortis. Vestibulum varius, erat vitae viverra convallis, nisi purus volutpat nisi, et tincidunt lectus enim et libero. Donec
  mattis auctor porta. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+			
+			Proin ornare ipsum eu lacus adipiscing varius. Pellentesque laoreet fermentum tellus, quis dapibus sapien mattis vitae. Maecenas suscipit tempor interdum. Maecenas ut eleifend urna. Phasellus ut auctor sem. Fusce ligula mauris, fermentum et vestibulum et, lacinia a lacus. In vulputate blandit purus nec sollicitudin. Duis tincidunt, turpis vitae faucibus dictum, mauris justo aliquet felis, eu suscipit ipsum lorem vitae metus. Nam commodo tincidunt sagittis. Praesent sit amet neque sed diam convallis blandit. Donec porttitor varius lacus, eget ultricies sem varius sed. Nullam eget risus nec turpis tincidunt convallis id eu mi.
+			
+			Integer non augue orci, non venenatis ligula. Vivamus rutrum purus id neque vehicula tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. Maecenas aliquet facilisis enim. Curabitur commodo egestas nisl eget ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut feugiat, arcu quis cursus vehicula, lorem dolor viverra mi, ac gravida elit lorem at est. In ac ligula egestas tortor consectetur malesuada a cursus nisi. Aenean quis velit augue. Nunc justo diam, iaculis in consequat non, fringilla ac ipsum. Nunc sit amet lacus lectus. In est augue, mollis ullamcorper scelerisque ut, vulputate at massa. Cras eu felis ut dolor auctor porttitor. Aliquam eu risus ut arcu pulvinar lobortis vitae non nibh.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris luctus consequat arcu, viverra eleifend libero vulputate sed. Vivamus consequat arcu pharetra erat bibendum ac suscipit nibh ornare. In vel sapien quis ipsum eleifend gravida id vitae est. Phasellus quis mi odio. Nunc rhoncus, tortor vitae feugiat vehicula, diam diam tempus diam, vel iaculis orci dui id lectus. Morbi rutrum tempus sodales. In nisi turpis, fringilla lobortis fermentum vel, tincidunt eget massa. Nullam facilisis tortor eu nulla pharetra nec malesuada dui sagittis. Quisque elementum vulputate orci ac luctus. Morbi et justo ipsum, eget consequat mi.
+			
+			Integer placerat purus elementum augue ultrices pharetra. Maecenas at diam purus, nec fermentum urna. Praesent ut commodo diam. Suspendisse potenti. Aenean eu lectus accumsan metus varius rhoncus dictum quis purus. Morbi vitae turpis elit, ut euismod justo. Sed sollicitudin malesuada risus, et iaculis lectus aliquet sed. Quisque tellus sem, aliquam et mattis ut, condimentum mattis nisl. Fusce sit amet lorem et lectus scelerisque placerat. Quisque et magna purus. Nullam quis sapien nisi. Integer in ligula vel magna vulputate semper eu nec velit. Duis sollicitudin vestibulum mauris quis malesuada. Praesent luctus sapien et felis convallis eu egestas erat consequat. Nulla tincidunt sagittis euismod. Nunc laoreet odio sollicitudin tortor mattis rhoncus. Curabitur lacinia, lorem nec tempus fringilla, dolor magna tincidunt eros, eu interdum turpis lorem id arcu.
+			
+			Pellentesque pellentesque lorem quis sem volutpat luctus. Proin malesuada nunc sed mi fringilla blandit sit amet ut nibh. Nulla vestibulum dolor ac leo venenatis in condimentum sem varius. Cras nec mattis ipsum. Nulla id libero tellus, ac rutrum elit. Duis eget orci lectus, eget pulvinar justo. Ut ornare erat vel nisl ornare id rutrum velit aliquet. Mauris dapibus commodo tempus. Donec tempus eleifend urna eu imperdiet. Fusce aliquam leo in ipsum egestas ac sollicitudin arcu pharetra. Proin elementum gravida condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fringilla lacinia dolor quis cursus. Sed euismod lorem malesuada libero porttitor pellentesque. Nulla facilisi. Proin mattis eros convallis nisi vulputate in molestie ipsum aliquet. Proin a eros eu sapien faucibus condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis id nibh magna. Proin congue, enim vel imperdiet rutrum, l
 eo augue aliquam turpis, sed scelerisque dolor leo et elit.
+			
+			In vitae magna eget velit condimentum vestibulum. Proin sapien purus, elementum et tincidunt sed, interdum eu orci. Vivamus eget sapien sit amet tellus vulputate euismod eget non ante. Duis consequat urna at quam pharetra vel scelerisque lectus cursus. Aenean varius, sem a venenatis vulputate, ante arcu sodales nulla, id mollis nulla lacus quis sapien. Fusce egestas turpis risus, ut feugiat ante. Fusce pretium diam quis sapien scelerisque consectetur. Cras at ante id risus aliquet cursus quis semper enim. Duis non turpis eu metus pretium interdum. Duis leo sem, elementum ut accumsan sit amet, facilisis eget arcu. Phasellus lacus velit, bibendum in porta eget, aliquam ac felis. Quisque neque eros, scelerisque id semper et, sodales sit amet risus. Aliquam ac tellus eget lacus dictum pretium nec sit amet libero. Maecenas nec nibh lectus, a dignissim leo. Quisque congue sem a risus gravida at congue lectus pellentesque.
+			
+			Nulla leo nulla, sagittis ac interdum ut, faucibus in est. Fusce imperdiet mauris nec lorem luctus sit amet commodo tortor pellentesque. Maecenas lacinia metus ut erat hendrerit ac ultrices purus sagittis. Sed elementum, risus ut elementum molestie, magna felis viverra ipsum, vel lobortis tellus libero id justo. Duis eget sapien convallis sem bibendum scelerisque vel tempor mauris. Etiam ut lorem ipsum, ac gravida lectus. Morbi aliquam, orci non ullamcorper auctor, elit lacus condimentum odio, sit amet lacinia eros ipsum at eros. Vestibulum dictum eros sapien, sed imperdiet sem. Etiam id enim leo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla leo magna, suscipit quis lobortis id, egestas id purus. Maecenas eu est turpis, et euismod mi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ligula nibh, iaculis eu porta eget, euismod in turpis. Sed turpis velit, porta ac scelerisq
 ue ac, accumsan vel nulla. Ut nec ante posuere lacus tristique ornare. Quisque viverra rutrum commodo.
+			
+			Sed magna diam, ultricies ultricies tincidunt sit amet, ultricies quis felis. Suspendisse ac mauris mi, non pretium erat. Sed faucibus aliquet metus sit amet mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lorem lacus, convallis porta fermentum ut, adipiscing quis quam. Maecenas bibendum dapibus eros in convallis. Suspendisse ut odio augue. Morbi mattis, quam a posuere placerat, leo dui cursus felis, ac mollis purus odio sed quam. Mauris elementum aliquet mauris, commodo tristique tellus semper quis. Quisque tellus justo, dapibus eget pretium id, viverra non turpis. Pellentesque luctus pulvinar dignissim.
+			
+			Proin molestie rutrum est, ac placerat arcu placerat et. Sed rhoncus sollicitudin augue, id vulputate nunc iaculis id. Vivamus consectetur placerat mi, vehicula faucibus ipsum placerat ut. In quis dui ligula, non lobortis tortor. Nunc sit amet quam sem, at faucibus neque. Sed scelerisque lacinia aliquam. Nunc quis dolor sit amet velit convallis eleifend a interdum mi. Sed tellus est, rutrum sit amet euismod non, sollicitudin sed lorem. Cras id aliquam est. Curabitur velit neque, hendrerit a volutpat sed, iaculis vitae massa. Duis non est vel ligula hendrerit pellentesque et vitae velit. Ut sed felis metus, quis convallis eros. Aliquam sit amet nunc at justo egestas aliquam. Morbi ut ante eros, in pretium metus. Sed fermentum orci sit amet mauris lobortis tincidunt et eget arcu. Morbi mattis, elit vel dictum sollicitudin, lectus libero ultrices nunc, sed dapibus urna felis quis orci. Donec eu urna at nisi tempus pretium at ac dui. In suscipit elementum congue.
+			
+			Pellentesque lorem purus, dignissim eget congue sed, gravida id orci. Aenean ligula lacus, accumsan vitae pulvinar ac, sollicitudin vel augue. Sed nec ante vel ante dignissim cursus. Morbi eleifend, nunc nec luctus pretium, eros nulla auctor mi, at commodo magna mi in lectus. Fusce et nisl tellus, id ullamcorper nisl. Vestibulum iaculis felis non sem bibendum sed feugiat lorem ultrices. In mauris nisl, eleifend at fringilla vitae, ullamcorper ut neque. Vestibulum eget turpis ac enim porta porttitor tincidunt sit amet erat. Nullam accumsan risus neque, et euismod leo. Nam nibh quam, congue eget blandit in, tristique quis mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at nibh justo, eleifend hendrerit enim.
+			
+			Duis at porta lectus. Duis placerat imperdiet aliquam. Vestibulum tortor augue, aliquam nec venenatis in, ultricies sit amet justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus nec orci vel ligula eleifend ultrices quis euismod diam. Suspendisse eleifend tincidunt nisl non aliquam. Donec sagittis odio eu sapien ultrices mattis. Nulla sagittis pulvinar est, rhoncus mollis dui gravida eget. Cras et nisi ante, in luctus leo. Phasellus a porttitor metus. Nam tortor enim, porta cursus tempor vel, rhoncus ut tortor. Morbi enim velit, dictum vel pulvinar quis, interdum nec tortor. Vivamus et justo ligula, nec commodo lorem. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur ligula mi, eleifend a pellentesque id, adipiscing id metus. Nunc vel dui et enim porttitor sollicitudin. In pretium ultrices congue. Donec malesuada convallis convallis. Aliquam quis risus lorem.
+			
+			In est lectus, rutrum vel convallis sed, egestas vitae leo. Donec augue odio, ultricies in consequat non, scelerisque nec nisi. Suspendisse potenti. Pellentesque ullamcorper arcu vel magna iaculis auctor. Pellentesque blandit accumsan lorem sagittis accumsan. Donec dignissim porttitor urna, non blandit magna pulvinar in. Donec tristique lacus sit amet nulla vehicula iaculis. Vestibulum pharetra odio lorem, at volutpat tellus. Fusce quis lorem odio. Sed ornare purus id sem elementum egestas ac sed nunc. Quisque convallis, augue vitae porta lobortis, nibh magna condimentum massa, id tincidunt magna magna ac odio. Donec quam nisi, bibendum et mollis at, molestie vitae mi. Suspendisse potenti.
+			
+			Nullam dolor nunc, condimentum ut vehicula sollicitudin, lacinia sit amet sapien. Nullam et enim id tortor suscipit ultrices. Nulla ut lorem leo, vel sodales leo. Donec erat nulla, sollicitudin eu varius sed, consectetur vel risus. Sed vehicula pulvinar lorem, at scelerisque dolor iaculis vitae. In purus ante, malesuada vitae euismod et, dictum sed ipsum. Ut nibh sapien, tristique sit amet sagittis eget, adipiscing at dolor. Nunc sit amet risus porta ligula rutrum commodo a a diam. Duis adipiscing enim ipsum, sit amet auctor diam. Sed vel tellus et sapien commodo molestie. Sed id risus consectetur lectus malesuada lacinia. Sed a aliquam enim. Fusce venenatis leo faucibus magna tempus sit amet sodales nisi pharetra. Vestibulum velit justo, pulvinar nec euismod facilisis, aliquet quis eros. In erat mauris, cursus a adipiscing non, semper eu erat. Donec id est mauris. Fusce fermentum fringilla vehicula. Mauris malesuada ligula placerat lorem tristique eu dignissim est feugiat.
+			
+			Vestibulum commodo elit ut nisi iaculis vehicula. Quisque bibendum, eros ut cursus dictum, risus mauris volutpat est, sed mollis metus justo et enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed et eros eget sapien aliquam cursus vel et erat. In commodo nunc sodales nibh sagittis vehicula. Nam dapibus justo sed nulla pellentesque faucibus. Nulla posuere ullamcorper libero, in porttitor diam vulputate vel. Sed vel dolor est. Proin sit amet convallis dui. Ut et libero quis sem vulputate rutrum eget ac dolor. Morbi eget massa dolor. In hac habitasse platea dictumst. Pellentesque consectetur arcu quis lacus varius bibendum. Donec placerat fringilla nulla vel semper.
+			
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce mollis nisi pharetra massa rhoncus tempus. Sed ac mauris ut sapien hendrerit dignissim eu a urna. Curabitur pretium fringilla orci ut dictum. In vulputate urna in diam scelerisque lobortis. Sed in dolor sit amet erat interdum commodo. Etiam dignissim consectetur nibh sit amet lobortis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut laoreet nisl a nunc suscipit et luctus est bibendum. Morbi in elit elit. Donec vitae diam enim. Praesent arcu justo, faucibus at varius vitae, porta laoreet elit. Donec eleifend mattis semper. Morbi tempus neque et nisl rhoncus adipiscing. Etiam venenatis consectetur nisl, eu congue velit lacinia sit amet. Nunc venenatis lacus a mi aliquet at volutpat elit semper. Pellentesque luctus laoreet sapien, ac tempus elit dignissim id.
+			
+			Aliquam cursus mattis bibendum. Praesent rhoncus augue sed ligula iaculis dapibus. Fusce facilisis eleifend leo ut dignissim. Morbi gravida luctus velit sit amet suscipit. In justo turpis, condimentum eget pharetra ac, consectetur vitae nisi. Suspendisse potenti. Proin euismod ante vitae lorem luctus tempus. Suspendisse sodales nisi in mauris elementum congue a dictum ipsum. Duis a mattis dui. Nulla ac ipsum id purus hendrerit pellentesque rhoncus quis odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at mauris egestas mi tristique mattis. Vivamus ac risus vitae ante congue porta. Suspendisse ut lacus dolor. Suspendisse quis quam metus, et porta urna. Nulla malesuada porta lacus at dictum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
+			
+			Donec et dignissim ligula. Phasellus vitae interdum mauris. Curabitur sit amet lacus sed magna consequat dictum. Phasellus laoreet enim sit amet metus pharetra pulvinar ut aliquam nisl. Praesent et metus nisl. Nulla nec elit nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer commodo luctus commodo. Fusce sed turpis facilisis urna laoreet semper. Pellentesque quis tellus ut augue commodo venenatis euismod a nulla. Integer tempus lacinia urna non pharetra. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus nec eros arcu. Aenean nec laoreet diam. In eget arcu hendrerit ligula fermentum interdum eu sagittis massa. Cras dapibus magna quis diam venenatis eget porttitor lacus ornare.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris dapibus faucibus vehicula. Nulla facilisi. Pellentesque lorem nunc, tempor id molestie et, mollis ut velit. Sed ligula nisl, lobortis vitae ornare quis, euismod placerat purus. Nullam convallis mi sed orci rutrum nec vulputate odio pulvinar. Cras mattis vehicula pulvinar. Cras cursus condimentum pretium. Donec ornare dui nec est hendrerit et posuere nunc facilisis. Mauris libero sem, semper semper laoreet in, sollicitudin eu dolor. Integer justo orci, ultricies et facilisis nec, tincidunt at justo. In tincidunt porttitor diam ut consectetur. Nullam sit amet lorem lacus. Fusce lacus sapien, dapibus vel commodo sit amet, eleifend in orci. Sed consectetur ligula eget purus placerat a accumsan turpis scelerisque. Donec in nibh vitae lacus congue dictum.
+			
+			Etiam at mollis nisl. Mauris in iaculis magna. In vel elit consectetur magna tempus adipiscing vitae eu sapien. Nullam nisl eros, aliquet vitae varius vel, vestibulum fermentum neque. Suspendisse arcu quam, elementum nec tincidunt vel, egestas in lectus. Quisque at purus justo, sed blandit nisi. Sed ac magna felis. Fusce dui risus, placerat sit amet ullamcorper mattis, dapibus eu eros. Nam pharetra egestas condimentum. Vestibulum ac viverra nisi. Maecenas ut libero nunc, eu auctor elit. Curabitur pellentesque facilisis fermentum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin mattis lacus at felis dapibus in condimentum metus sagittis.
+			
+			Morbi vitae turpis sed massa ullamcorper imperdiet vitae vitae nisi. Phasellus sodales lobortis erat, nec sodales massa pulvinar vitae. Quisque pharetra, nulla quis bibendum condimentum, nisi ligula interdum metus, et aliquet enim dolor non magna. In venenatis, mi vel aliquam bibendum, purus tellus malesuada nisl, vel lobortis metus arcu et neque. Donec accumsan dolor vel est venenatis facilisis mattis eget lectus. Morbi nec lorem et metus eleifend semper. Suspendisse mauris dolor, commodo eu euismod sed, mollis id tellus. Nullam volutpat, dolor ac scelerisque porttitor, enim orci vestibulum enim, in dapibus mauris sapien eu est. Nullam luctus sodales lorem, sit amet imperdiet arcu sagittis nec. Nulla sed libero mi, nec luctus arcu. Aliquam nisi velit, tempor sed pulvinar id, ultrices a velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut a venenatis ligula.
+			
+			Nam porta viverra risus quis eleifend. Maecenas imperdiet auctor dui. Vivamus ac lobortis nulla. Sed non pharetra libero. Vivamus facilisis consequat hendrerit. Aliquam mattis eleifend libero non ultrices. Suspendisse sit amet venenatis dolor. Sed euismod euismod tincidunt. Mauris dictum feugiat lectus eget convallis. Aliquam nunc nunc, euismod a interdum a, pretium a diam. Etiam nec libero ante, nec gravida eros. Donec a diam in tellus dignissim suscipit eget ac felis. Nunc sed accumsan risus. Suspendisse ante lorem, facilisis at aliquet quis, mattis nec sem.
+			
+			Ut fringilla gravida nisl, sit amet blandit mi imperdiet et. In hac habitasse platea dictumst. Vivamus eu neque sed enim sollicitudin suscipit. Aliquam suscipit aliquet tortor, nec sodales lacus condimentum vitae. Aenean pharetra velit vel nisl iaculis eget vehicula massa fringilla. Sed ut faucibus lorem. Fusce non eros diam, in auctor quam. Donec vulputate placerat consectetur. Nam vehicula, dui semper porta elementum, lorem libero scelerisque magna, id semper diam sem eget nibh. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aliquam quis risus non diam commodo ullamcorper. In elementum dapibus erat a viverra.
+			
+			Praesent consectetur enim ac enim mollis eu vehicula justo luctus. Nam tristique nisi ultricies dolor pulvinar vulputate. Morbi egestas, mi lobortis feugiat mollis, turpis sem porttitor ante, at porta neque nunc congue purus. In vel quam dolor. Aliquam erat volutpat. Nunc semper tempor ipsum vitae facilisis. Nam eu consectetur elit. In aliquet feugiat tellus. Morbi porta pharetra fringilla. Sed euismod fringilla est, quis malesuada neque dictum vitae. Fusce sed lacus non nisi laoreet iaculis. Aenean fringilla tincidunt est. Nulla eu mi justo, quis semper erat. Nunc id diam vitae dolor viverra placerat vitae eu turpis. Praesent sed nisl quis lectus gravida euismod. Sed eget lacus libero. Proin eleifend pharetra sem vehicula ornare.
+			
+			Ut mi arcu, accumsan quis molestie sit amet, hendrerit sit amet magna. Praesent sodales nisl quis libero lobortis mollis. Mauris lectus ipsum, sodales a tempus eget, congue vel velit. Proin auctor sapien rhoncus lectus iaculis facilisis. Sed orci lacus, feugiat ut bibendum non, molestie quis ipsum. Vivamus et nisl vel eros varius dictum dignissim ut purus. Morbi ut risus et nunc ultricies vehicula vel vitae augue. Curabitur nec velit tellus. Donec dapibus, magna in tincidunt bibendum, neque tellus aliquam nulla, vitae pretium metus orci dignissim libero. Cras eget eros et dolor faucibus pretium quis vel tellus. Quisque ullamcorper bibendum ligula, eu tempor leo eleifend porttitor. Donec nisi enim, tempor vitae tempus vitae, molestie et orci. Proin libero libero, congue at elementum ut, congue in justo. Cras quis enim ac leo sollicitudin vehicula. Fusce sed diam sed neque consectetur dictum ac nec diam.
+			
+			Morbi accumsan porttitor sapien quis porttitor. Duis id quam nisl, sodales elementum lacus. Vestibulum eget quam ac justo pellentesque volutpat. Praesent ut vestibulum odio. Pellentesque eget lobortis velit. Proin congue dignissim tempus. Duis eget justo sit amet risus consectetur suscipit non in nunc. Morbi iaculis luctus egestas. Mauris pretium, mauris ac dapibus aliquam, dolor velit dapibus est, ut semper diam nisi nec eros. Nam mollis diam congue nulla tempus ut euismod felis imperdiet.
+			
+			Maecenas hendrerit interdum enim nec egestas. Mauris in sapien orci, at malesuada mi. Proin faucibus ultricies est, vitae luctus elit condimentum eget. Donec suscipit, lorem sit amet rhoncus faucibus, erat orci sollicitudin tortor, ut placerat dolor metus in dolor. Proin ac mauris et neque rhoncus accumsan. Nunc sodales ultrices velit. In lacinia eleifend pretium. Nullam facilisis egestas libero at volutpat. Morbi aliquet volutpat nibh. Etiam sed nunc tortor, et hendrerit augue. Quisque vitae vulputate ante. Sed bibendum quam a magna rutrum pulvinar.
+			
+			Donec tincidunt nunc id libero dapibus interdum. Nam volutpat ligula et nulla fermentum nec lacinia magna aliquam. Sed id ligula velit, at vestibulum dui. Etiam libero arcu, fringilla non porttitor eget, mattis eu risus. Pellentesque vel velit leo, nec mattis eros. Donec venenatis pellentesque metus ut ultricies. Nullam nec bibendum lorem. Etiam nisi nisl, lobortis ac tempor at, pulvinar aliquam sapien. Quisque nulla turpis, ultrices et euismod in, interdum eu odio. Pellentesque suscipit dui nec sem euismod ac tincidunt libero malesuada. Fusce quis vulputate erat. Suspendisse rutrum purus a nunc commodo scelerisque at a enim. Ut viverra massa ut est tempor et fringilla ligula pharetra.
+			
+			Nam tempus orci vel elit viverra molestie. Suspendisse lobortis ultrices ipsum malesuada lobortis. Duis imperdiet lorem in risus interdum commodo. Nam elementum mollis arcu eget pellentesque. Sed vel lectus et odio imperdiet ultrices. Curabitur eget diam eu arcu fermentum condimentum. Proin elementum laoreet aliquet. Nullam faucibus fringilla tortor. Proin nulla neque, tincidunt sit amet interdum eget, laoreet a ligula. Integer rutrum feugiat convallis. Aenean pharetra mi eu mi porttitor nec interdum turpis sollicitudin. Sed justo urna, posuere sed aliquet a, fringilla in nulla. Vestibulum in nisi ac mi eleifend gravida.
+			
+			Ut quis ornare mauris. Phasellus sapien dolor, fermentum quis volutpat non, sollicitudin a nulla. Donec aliquet eros vel velit lobortis laoreet. Nulla eget felis sit amet nibh placerat dictum. Morbi vestibulum pharetra porta. Phasellus ligula tellus, molestie non vestibulum eget, viverra molestie velit. Morbi pretium elit ut nisl imperdiet ultrices aliquam dui iaculis. Suspendisse id condimentum nisl. In hac habitasse platea dictumst. Donec non purus orci, sed euismod velit. In hac habitasse platea dictumst. Ut ultricies enim et diam elementum porttitor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed pharetra dui semper mi malesuada sit amet interdum dolor dapibus. Cras et neque facilisis diam aliquam ullamcorper at vitae lorem.
+			
+			Nullam lacinia laoreet dolor vitae tincidunt. Mauris volutpat nisi et neque lacinia consequat nec accumsan purus. Vestibulum ac est quis ante commodo vulputate et non turpis. Vivamus sit amet eros ac neque feugiat laoreet et a mi. Aenean ultricies pretium condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut lacus magna, sagittis at tempor in, bibendum at odio. Donec auctor leo nec massa vehicula quis mollis lacus hendrerit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec erat nulla, tristique vel adipiscing a, faucibus id erat. Sed suscipit nunc sit amet dui condimentum fermentum.
+			
+			Etiam condimentum, risus eu ornare vehicula, libero lacus porttitor tortor, et feugiat libero augue condimentum nunc. Nulla facilisi. Aliquam lacinia turpis leo, ut tincidunt metus. Phasellus urna dui, vehicula vitae convallis sed, pharetra eu lorem. Cras accumsan vestibulum cursus. Phasellus congue nisl sapien, sit amet fermentum magna. Cras porta pulvinar libero eu luctus. Nullam sodales suscipit arcu eu malesuada. In aliquet vulputate euismod. Phasellus eu mi turpis, eget bibendum urna. Aenean luctus dolor in nisl adipiscing aliquam. Donec in tempor diam. Nam tristique odio nec ipsum semper interdum sit amet aliquet magna. Sed hendrerit, tortor eget faucibus facilisis, diam nisl dignissim nisl, a bibendum nisl dui sit amet lacus. Vestibulum fermentum leo in elit consequat a viverra tellus accumsan. Cras a condimentum mauris. Aliquam quis arcu tellus. Integer dictum sodales dui, a fringilla eros porta placerat. Vestibulum feugiat, odio a cursus aliquet, erat nisl volutpat odio,
  blandit sodales turpis est nec purus. Nullam tincidunt mi non odio sagittis nec facilisis velit porttitor.
+			
+			In pulvinar mi sed ligula imperdiet quis sollicitudin nisi dignissim. Fusce at sodales massa. Phasellus vulputate nibh at justo mattis porttitor gravida augue faucibus. Fusce sit amet quam risus, vel malesuada risus. Aliquam gravida venenatis libero quis congue. In nec ipsum id mauris pretium pharetra. Duis tincidunt hendrerit sollicitudin. Cras condimentum diam et enim facilisis lacinia. Donec posuere rhoncus ante, eu ullamcorper est commodo vel. Sed tellus lectus, congue ut suscipit sed, ultricies nec nulla. Cras malesuada dolor et erat tincidunt dignissim. Quisque eu turpis est, a consectetur orci. Pellentesque neque orci, tristique sit amet volutpat ac, tempus eget urna. Nunc pharetra sapien eget lacus sagittis venenatis. Donec ac leo in erat ornare bibendum. Suspendisse vel dui erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+			
+			Quisque eget turpis dui, vel semper massa. Sed vel dapibus dui. Etiam non sollicitudin orci. Vivamus lectus lectus, iaculis quis molestie id, euismod a nisl. Fusce malesuada scelerisque ligula, nec molestie metus adipiscing quis. Curabitur laoreet lectus vitae eros sagittis rutrum. Phasellus leo ante, aliquet sed porttitor et, sollicitudin vel ligula. Cras bibendum lectus aliquet dui dapibus consequat. Vestibulum gravida lorem sit amet augue tincidunt ac eleifend leo mollis. Quisque id fringilla lectus. Aenean ac felis at dolor consequat porta. Nulla feugiat sem vel justo eleifend id dignissim dui auctor. Aliquam hendrerit vulputate lorem, ut cursus orci placerat at. Praesent eget est erat. Morbi a lorem tortor.
+			
+			Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In hac habitasse platea dictumst. Quisque dictum, enim nec adipiscing accumsan, eros justo aliquet lacus, at dignissim nulla lectus eu justo. Cras auctor luctus purus vitae eleifend. Cras at est eu odio rutrum sollicitudin. Aenean scelerisque volutpat risus sit amet accumsan. Sed eget orci dui. Vestibulum est augue, malesuada eu venenatis tristique, lobortis eu sapien. Vivamus eget sapien non urna iaculis sodales ac a neque. Praesent accumsan purus et nisl hendrerit non condimentum erat varius. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras non purus ac ante faucibus ullamcorper. Mauris blandit pretium nulla, vitae imperdiet quam condimentum nec. Sed mattis urna id felis bibendum dignissim. Maecenas in mi at tellus lobortis lobortis. Vestibulum varius, erat vitae viverra convallis, nisi purus volutpat nisi, et tincidunt lectus enim et libero. Donec
  mattis auctor porta. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
+			
+			Proin ornare ipsum eu lacus adipiscing varius. Pellentesque laoreet fermentum tellus, quis dapibus sapien mattis vitae. Maecenas suscipit tempor interdum. Maecenas ut eleifend urna. Phasellus ut auctor sem. Fusce ligula mauris, fermentum et vestibulum et, lacinia a lacus. In vulputate blandit purus nec sollicitudin. Duis tincidunt, turpis vitae faucibus dictum, mauris justo aliquet felis, eu suscipit ipsum lorem vitae metus. Nam commodo tincidunt sagittis. Praesent sit amet neque sed diam convallis blandit. Donec porttitor varius lacus, eget ultricies sem varius sed. Nullam eget risus nec turpis tincidunt convallis id eu mi.
+			
+			Integer non augue orci, non venenatis ligula. Vivamus rutrum purus id neque vehicula tincidunt. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla facilisi. Maecenas aliquet facilisis enim. Curabitur commodo egestas nisl eget ullamcorper. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut feugiat, arcu quis cursus vehicula, lorem dolor viverra mi, ac gravida elit lorem at est. In ac ligula egestas tortor consectetur malesuada a cursus nisi. Aenean quis velit augue. Nunc justo diam, iaculis in consequat non, fringilla ac ipsum. Nunc sit amet lacus lectus. In est augue, mollis ullamcorper scelerisque ut, vulputate at massa. Cras eu felis ut dolor auctor porttitor. Aliquam eu risus ut arcu pulvinar lobortis vitae non nibh.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris luctus consequat arcu, viverra eleifend libero vulputate sed. Vivamus consequat arcu pharetra erat bibendum ac suscipit nibh ornare. In vel sapien quis ipsum eleifend gravida id vitae est. Phasellus quis mi odio. Nunc rhoncus, tortor vitae feugiat vehicula, diam diam tempus diam, vel iaculis orci dui id lectus. Morbi rutrum tempus sodales. In nisi turpis, fringilla lobortis fermentum vel, tincidunt eget massa. Nullam facilisis tortor eu nulla pharetra nec malesuada dui sagittis. Quisque elementum vulputate orci ac luctus. Morbi et justo ipsum, eget consequat mi.
+			
+			Integer placerat purus elementum augue ultrices pharetra. Maecenas at diam purus, nec fermentum urna. Praesent ut commodo diam. Suspendisse potenti. Aenean eu lectus accumsan metus varius rhoncus dictum quis purus. Morbi vitae turpis elit, ut euismod justo. Sed sollicitudin malesuada risus, et iaculis lectus aliquet sed. Quisque tellus sem, aliquam et mattis ut, condimentum mattis nisl. Fusce sit amet lorem et lectus scelerisque placerat. Quisque et magna purus. Nullam quis sapien nisi. Integer in ligula vel magna vulputate semper eu nec velit. Duis sollicitudin vestibulum mauris quis malesuada. Praesent luctus sapien et felis convallis eu egestas erat consequat. Nulla tincidunt sagittis euismod. Nunc laoreet odio sollicitudin tortor mattis rhoncus. Curabitur lacinia, lorem nec tempus fringilla, dolor magna tincidunt eros, eu interdum turpis lorem id arcu.
+			
+			Pellentesque pellentesque lorem quis sem volutpat luctus. Proin malesuada nunc sed mi fringilla blandit sit amet ut nibh. Nulla vestibulum dolor ac leo venenatis in condimentum sem varius. Cras nec mattis ipsum. Nulla id libero tellus, ac rutrum elit. Duis eget orci lectus, eget pulvinar justo. Ut ornare erat vel nisl ornare id rutrum velit aliquet. Mauris dapibus commodo tempus. Donec tempus eleifend urna eu imperdiet. Fusce aliquam leo in ipsum egestas ac sollicitudin arcu pharetra. Proin elementum gravida condimentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed fringilla lacinia dolor quis cursus. Sed euismod lorem malesuada libero porttitor pellentesque. Nulla facilisi. Proin mattis eros convallis nisi vulputate in molestie ipsum aliquet. Proin a eros eu sapien faucibus condimentum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis id nibh magna. Proin congue, enim vel imperdiet rutrum, l
 eo augue aliquam turpis, sed scelerisque dolor leo et elit.
+			
+			In vitae magna eget velit condimentum vestibulum. Proin sapien purus, elementum et tincidunt sed, interdum eu orci. Vivamus eget sapien sit amet tellus vulputate euismod eget non ante. Duis consequat urna at quam pharetra vel scelerisque lectus cursus. Aenean varius, sem a venenatis vulputate, ante arcu sodales nulla, id mollis nulla lacus quis sapien. Fusce egestas turpis risus, ut feugiat ante. Fusce pretium diam quis sapien scelerisque consectetur. Cras at ante id risus aliquet cursus quis semper enim. Duis non turpis eu metus pretium interdum. Duis leo sem, elementum ut accumsan sit amet, facilisis eget arcu. Phasellus lacus velit, bibendum in porta eget, aliquam ac felis. Quisque neque eros, scelerisque id semper et, sodales sit amet risus. Aliquam ac tellus eget lacus dictum pretium nec sit amet libero. Maecenas nec nibh lectus, a dignissim leo. Quisque congue sem a risus gravida at congue lectus pellentesque.
+			
+			Nulla leo nulla, sagittis ac interdum ut, faucibus in est. Fusce imperdiet mauris nec lorem luctus sit amet commodo tortor pellentesque. Maecenas lacinia metus ut erat hendrerit ac ultrices purus sagittis. Sed elementum, risus ut elementum molestie, magna felis viverra ipsum, vel lobortis tellus libero id justo. Duis eget sapien convallis sem bibendum scelerisque vel tempor mauris. Etiam ut lorem ipsum, ac gravida lectus. Morbi aliquam, orci non ullamcorper auctor, elit lacus condimentum odio, sit amet lacinia eros ipsum at eros. Vestibulum dictum eros sapien, sed imperdiet sem. Etiam id enim leo. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla leo magna, suscipit quis lobortis id, egestas id purus. Maecenas eu est turpis, et euismod mi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum ligula nibh, iaculis eu porta eget, euismod in turpis. Sed turpis velit, porta ac scelerisq
 ue ac, accumsan vel nulla. Ut nec ante posuere lacus tristique ornare. Quisque viverra rutrum commodo.
+			
+			Sed magna diam, ultricies ultricies tincidunt sit amet, ultricies quis felis. Suspendisse ac mauris mi, non pretium erat. Sed faucibus aliquet metus sit amet mattis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris lorem lacus, convallis porta fermentum ut, adipiscing quis quam. Maecenas bibendum dapibus eros in convallis. Suspendisse ut odio augue. Morbi mattis, quam a posuere placerat, leo dui cursus felis, ac mollis purus odio sed quam. Mauris elementum aliquet mauris, commodo tristique tellus semper quis. Quisque tellus justo, dapibus eget pretium id, viverra non turpis. Pellentesque luctus pulvinar dignissim.
+			
+			Proin molestie rutrum est, ac placerat arcu placerat et. Sed rhoncus sollicitudin augue, id vulputate nunc iaculis id. Vivamus consectetur placerat mi, vehicula faucibus ipsum placerat ut. In quis dui ligula, non lobortis tortor. Nunc sit amet quam sem, at faucibus neque. Sed scelerisque lacinia aliquam. Nunc quis dolor sit amet velit convallis eleifend a interdum mi. Sed tellus est, rutrum sit amet euismod non, sollicitudin sed lorem. Cras id aliquam est. Curabitur velit neque, hendrerit a volutpat sed, iaculis vitae massa. Duis non est vel ligula hendrerit pellentesque et vitae velit. Ut sed felis metus, quis convallis eros. Aliquam sit amet nunc at justo egestas aliquam. Morbi ut ante eros, in pretium metus. Sed fermentum orci sit amet mauris lobortis tincidunt et eget arcu. Morbi mattis, elit vel dictum sollicitudin, lectus libero ultrices nunc, sed dapibus urna felis quis orci. Donec eu urna at nisi tempus pretium at ac dui. In suscipit elementum congue.
+			
+			Pellentesque lorem purus, dignissim eget congue sed, gravida id orci. Aenean ligula lacus, accumsan vitae pulvinar ac, sollicitudin vel augue. Sed nec ante vel ante dignissim cursus. Morbi eleifend, nunc nec luctus pretium, eros nulla auctor mi, at commodo magna mi in lectus. Fusce et nisl tellus, id ullamcorper nisl. Vestibulum iaculis felis non sem bibendum sed feugiat lorem ultrices. In mauris nisl, eleifend at fringilla vitae, ullamcorper ut neque. Vestibulum eget turpis ac enim porta porttitor tincidunt sit amet erat. Nullam accumsan risus neque, et euismod leo. Nam nibh quam, congue eget blandit in, tristique quis mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi at nibh justo, eleifend hendrerit enim.
+			
+			Duis at porta lectus. Duis placerat imperdiet aliquam. Vestibulum tortor augue, aliquam nec venenatis in, ultricies sit amet justo. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus nec orci vel ligula eleifend ultrices quis euismod diam. Suspendisse eleifend tincidunt nisl non aliquam. Donec sagittis odio eu sapien ultrices mattis. Nulla sagittis pulvinar est, rhoncus mollis dui gravida eget. Cras et nisi ante, in luctus leo. Phasellus a porttitor metus. Nam tortor enim, porta cursus tempor vel, rhoncus ut tortor. Morbi enim velit, dictum vel pulvinar quis, interdum nec tortor. Vivamus et justo ligula, nec commodo lorem. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur ligula mi, eleifend a pellentesque id, adipiscing id metus. Nunc vel dui et enim porttitor sollicitudin. In pretium ultrices congue. Donec malesuada convallis convallis. Aliquam quis risus lorem.
+			
+			In est lectus, rutrum vel convallis sed, egestas vitae leo. Donec augue odio, ultricies in consequat non, scelerisque nec nisi. Suspendisse potenti. Pellentesque ullamcorper arcu vel magna iaculis auctor. Pellentesque blandit accumsan lorem sagittis accumsan. Donec dignissim porttitor urna, non blandit magna pulvinar in. Donec tristique lacus sit amet nulla vehicula iaculis. Vestibulum pharetra odio lorem, at volutpat tellus. Fusce quis lorem odio. Sed ornare purus id sem elementum egestas ac sed nunc. Quisque convallis, augue vitae porta lobortis, nibh magna condimentum massa, id tincidunt magna magna ac odio. Donec quam nisi, bibendum et mollis at, molestie vitae mi. Suspendisse potenti.
+			
+			Nullam dolor nunc, condimentum ut vehicula sollicitudin, lacinia sit amet sapien. Nullam et enim id tortor suscipit ultrices. Nulla ut lorem leo, vel sodales leo. Donec erat nulla, sollicitudin eu varius sed, consectetur vel risus. Sed vehicula pulvinar lorem, at scelerisque dolor iaculis vitae. In purus ante, malesuada vitae euismod et, dictum sed ipsum. Ut nibh sapien, tristique sit amet sagittis eget, adipiscing at dolor. Nunc sit amet risus porta ligula rutrum commodo a a diam. Duis adipiscing enim ipsum, sit amet auctor diam. Sed vel tellus et sapien commodo molestie. Sed id risus consectetur lectus malesuada lacinia. Sed a aliquam enim. Fusce venenatis leo faucibus magna tempus sit amet sodales nisi pharetra. Vestibulum velit justo, pulvinar nec euismod facilisis, aliquet quis eros. In erat mauris, cursus a adipiscing non, semper eu erat. Donec id est mauris. Fusce fermentum fringilla vehicula. Mauris malesuada ligula placerat lorem tristique eu dignissim est feugiat.
+			
+			Vestibulum commodo elit ut nisi iaculis vehicula. Quisque bibendum, eros ut cursus dictum, risus mauris volutpat est, sed mollis metus justo et enim. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed et eros eget sapien aliquam cursus vel et erat. In commodo nunc sodales nibh sagittis vehicula. Nam dapibus justo sed nulla pellentesque faucibus. Nulla posuere ullamcorper libero, in porttitor diam vulputate vel. Sed vel dolor est. Proin sit amet convallis dui. Ut et libero quis sem vulputate rutrum eget ac dolor. Morbi eget massa dolor. In hac habitasse platea dictumst. Pellentesque consectetur arcu quis lacus varius bibendum. Donec placerat fringilla nulla vel semper.
+			
+			Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Fusce mollis nisi pharetra massa rhoncus tempus. Sed ac mauris ut sapien hendrerit dignissim eu a urna. Curabitur pretium fringilla orci ut dictum. In vulputate urna in diam scelerisque lobortis. Sed in dolor sit amet erat interdum commodo. Etiam dignissim consectetur nibh sit amet lobortis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Ut laoreet nisl a nunc suscipit et luctus est bibendum. Morbi in elit elit. Donec vitae diam enim. Praesent arcu justo, faucibus at varius vitae, porta laoreet elit. Donec eleifend mattis semper. Morbi tempus neque et nisl rhoncus adipiscing. Etiam venenatis consectetur nisl, eu congue velit lacinia sit amet. Nunc venenatis lacus a mi aliquet at volutpat elit semper. Pellentesque luctus laoreet sapien, ac tempus elit dignissim id.
+			
+			Aliquam cursus mattis bibendum. Praesent rhoncus augue sed ligula iaculis dapibus. Fusce facilisis eleifend leo ut dignissim. Morbi gravida luctus velit sit amet suscipit. In justo turpis, condimentum eget pharetra ac, consectetur vitae nisi. Suspendisse potenti. Proin euismod ante vitae lorem luctus tempus. Suspendisse sodales nisi in mauris elementum congue a dictum ipsum. Duis a mattis dui. Nulla ac ipsum id purus hendrerit pellentesque rhoncus quis odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In at mauris egestas mi tristique mattis. Vivamus ac risus vitae ante congue porta. Suspendisse ut lacus dolor. Suspendisse quis quam metus, et porta urna. Nulla malesuada porta lacus at dictum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
+			
+			Donec et dignissim ligula. Phasellus vitae interdum mauris. Curabitur sit amet lacus sed magna consequat dictum. Phasellus laoreet enim sit amet metus pharetra pulvinar ut aliquam nisl. Praesent et metus nisl. Nulla nec elit nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer commodo luctus commodo. Fusce sed turpis facilisis urna laoreet semper. Pellentesque quis tellus ut augue commodo venenatis euismod a nulla. Integer tempus lacinia urna non pharetra. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vivamus nec eros arcu. Aenean nec laoreet diam. In eget arcu hendrerit ligula fermentum interdum eu sagittis massa. Cras dapibus magna quis diam venenatis eget porttitor lacus ornare.
+			
+			Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris dapibus faucibus vehicula. Nulla facilisi. Pellentesque lorem nunc, tempor id molestie et, mollis ut velit. Sed ligula nisl, lobortis vitae ornare quis, euismod placerat purus. Nullam convallis mi sed orci rutrum nec vulputate odio pulvinar. Cras mattis vehicula pulvinar. Cras cursus condimentum pretium. Donec ornare dui nec est hendrerit et posuere nunc facilisis. Mauris libero sem, semper semper laoreet in, sollicitudin eu dolor. Integer justo orci, ultricies et facilisis nec, tincidunt at justo. In tincidunt porttitor diam ut consectetur. Nullam sit amet lorem lacus. Fusce lacus sapien, dapibus vel commodo sit amet, eleifend in orci. Sed consectetur ligula eget purus placerat a accumsan turpis scelerisque. Donec in nibh vitae lacus congue dictum.
+			
+			Etiam at mollis nisl. Mauris in iaculis magna. In vel elit consectetur magna tempus adipiscing vitae eu sapien. Nullam nisl eros, aliquet vitae varius vel, vestibulum fermentum neque. Suspendisse arcu quam, elementum nec tincidunt vel, egestas in lectus. Quisque at purus justo, sed blandit nisi. Sed ac magna felis. Fusce dui risus, placerat sit amet ullamcorper mattis, dapibus eu eros. Nam pharetra egestas condimentum. Vestibulum ac viverra nisi. Maecenas ut libero nunc, eu auctor elit. Curabitur pellentesque facilisis fermentum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin mattis lacus at felis dapibus in condimentum metus sagittis.
+			
+			Morbi vitae turpis sed massa ullamcorper imperdiet vitae vitae nisi. Phasellus sodales lobortis erat, nec sodales massa pulvinar vitae. Quisque pharetra, nulla quis bibendum condimentum, nisi ligula interdum metus, et aliquet enim dolor non magna. In venenatis, mi vel aliquam bibendum, purus tellus malesuada nisl, vel lobortis metus arcu et neque. Donec accumsan dolor vel est venenatis facilisis mattis eget lectus. Morbi nec lorem et metus eleifend semper. Suspendisse mauris dolor, commodo eu euismod sed, mollis id tellus. Nullam volutpat, dolor ac scelerisque porttitor, enim orci vestibulum enim, in dapibus mauris sapien eu est. Nullam luctus sodales lorem, sit amet imperdiet arcu sagittis nec. Nulla sed libero mi, nec luctus arcu. Aliquam nisi velit, tempor sed pulvinar id, ultrices a velit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Ut a venenatis ligula.
+			
+			Nam porta viverra risus quis eleifend. Maecenas imperdiet auctor dui. Vivamus ac lobortis nulla. Sed non pharetra libero. Vivamus facilisis consequat hendrerit. Aliquam mattis eleifend libero non ultrices. Suspendisse sit amet venenatis dolor. Sed euismod euismod tincidunt. Mauris dictum feugiat lectus eget convallis. Aliquam nunc nunc, euismod a interdum a, pretium a diam. Etiam nec libero ante, nec gravida eros. Donec a diam in tellus dignissim suscipit eget ac felis. Nunc sed accumsan risus. Suspendisse ante lorem, facilisis at aliquet quis, mattis nec sem.
+			
+			Ut fringilla gravida nisl, sit amet blandit mi imperdiet et. In hac habitasse platea dictumst. Vivamus eu neque sed enim sollicitudin suscipit. Aliquam suscipit aliquet tortor, nec sodales lacus condimentum vitae. Aenean pharetra velit vel nisl iaculis eget vehicula massa fringilla. Sed ut faucibus lorem. Fusce non eros diam, in auctor quam. Donec vulputate placerat consecte

<TRUNCATED>

[15/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
new file mode 100644
index 0000000..edd15e8
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/SpellUIForTLF.as
@@ -0,0 +1,597 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.IHighlighter;
+	import com.adobe.linguistics.spelling.ui.IWordProcessor;
+	import com.adobe.linguistics.spelling.ui.TLFHighlighter;
+	import com.adobe.linguistics.spelling.ui.TLFWordProcessor;
+	import com.adobe.linguistics.utils.TextFilter;
+	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.utils.Dictionary;
+	
+	import flashx.textLayout.TextLayoutVersion;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.DamageEvent;
+	import flashx.textLayout.events.FlowOperationEvent;
+	import flashx.textLayout.events.ScrollEvent;
+	import flashx.textLayout.events.UpdateCompleteEvent;
+	import flashx.textLayout.tlf_internal;
+	
+	
+	use namespace tlf_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 custom UI component built around TLF TextFlow.  </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>
+	 *
+	 * In order to display Squiggly custom right-click context menu, SpellUIForTLF extends TLF <code>ContainerController</code> class and overrides createContextMenu() method 
+	 * of <code>ContainerController</code>. This could have the following side-effects for a Squiggly client:
+	 * <ul>
+	 * 		<li>In case the Squiggly client application uses a derived controller that inherits from ContainerController class in order to show custom context menu items, Squiggly
+	 * 			context menu will override that. That essentially means that after SpellUIForTLF.enableSpelling() is called, client's own custom right-click menu items, if any, will not be
+	 * 			accessible. </li>
+	 * 		<li>Incase any ContainerController api needs to be called after SpellUIForTLF.enableSpelling() has been called, the client application will need to get the controller objects afresh 
+	 * 			from the TextFlow's FlowComposer. This is needed since SpellUIForTLF replaces ContainerController objects with new SquigglyCustomContainerController(derived from ContainerController) objects. </li> 
+	 * </ul>
+	 * 
+	 * 
+	 * <p><code>SpellUIForTLF</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 SpellUIForTLF
+	{
+		private var hh:IHighlighter;
+		private var hw:IWordProcessor;
+		
+		private var _checkLastWord:Boolean = true;
+		private var _spellingEnabled:Boolean;
+		
+		private var _actualParent:*;
+		
+
+        //New Added below
+		private var mTextFlow:TextFlow;
+		
+		
+		private var _dictname:String = new String();			
+
+		private var _userdict:UserDictionary = null;
+		private var _sharedobj:SharedObject = null;
+		//For filtering unwanted character
+		private var _textFilter:TextFilter= null;
+	//	private var scm:SpellingContextMenuForTLF;
+		
+		//private var _newchecker:SpellChecker = null;
+	//	private var _resource_locale:Object = null;
+		private var _thirdPatyResourceLocation:String= 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();
+
+		/**
+		 * Enables the spell checking feature for a TLF TextFlow. Once a TextFlow 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 TLF TextFlow object
+		 * @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 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/ActionScript/SquigglyTLFExample/src/SquigglyTLFExample.as
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+
+		public static function enableSpelling(comp:TextFlow, lang:String):void
+		{
+			if ( lang == null ) return;
+			if ( comp==null || _UITable[comp]!=undefined )
+				return;	
+			
+			// TODO: dangerous, is garbage collection going to clear this?
+			_UITable[comp]=new SpellUIForTLF(comp, lang);
+			_parentTable[comp] = comp;
+			_cacheDictTable[comp]=lang;			
+		}	
+	
+		/**
+		 * Set the spelling context menu entries. This uses the ActionScript Object class 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
+		 * to localize the context menu strings.
+		 *  
+		 * @param entries A Object 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.
+		 * 
+		 * @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 actionScript <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 specify 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">
+		 * SpellUIForTLF.spellingConfigUrl = "./config/MySpellingConfig.xml";
+		 * SpellUIForTLF.enableSpelling(textFlow, "en_US");
+		 * </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 TLF TextFlow.
+		 * 
+		 * @param comp	TLF TextFlow object on which to disable spell check.
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */
+		public static function disableSpelling(comp:TextFlow):void{
+			if ( _UITable[comp] == undefined )
+				return;
+			var _ui:SpellUIForTLF = _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;
+		}
+		public function get spellingEnabled():Boolean{
+			return _spellingEnabled;
+		}
+		
+		/**
+		 @private
+		 (This property is for Squiggly Developer use only.)
+		 */
+		public static function get parentComp():Dictionary {
+			return _parentTable;
+		}
+		
+				
+		/**
+		 * Constructs a SpellUI object.
+		 *  @private
+		 *	@param	textFiled	A Flex UI component to include spell-check capability
+		 *	@param	dict		A URL for Squiggly spelling dictionary.
+		 *
+		 * @playerversion Flash 10
+		 * @langversion 3.0
+		 */			
+		public function SpellUIForTLF(textModel:TextFlow, lang:String)
+		{		
+		
+			_actualParent = textModel;
+			mTextFlow = textModel;					
+			
+			//mTextFlow.addEventListener(flashx.textLayout.events.CompositionCompleteEvent.COMPOSITION_COMPLETE, spellCheckScreen,false, 0,true);
+			mTextFlow.addEventListener(flashx.textLayout.events.UpdateCompleteEvent.UPDATE_COMPLETE , spellCheckScreen, false, 0, true);
+			//mTextFlow.addEventListener(flashx.textLayout.events.StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, spellCheckScreen);
+			
+			_dictname = lang;	
+			_textFilter= new TextFilter();
+			loadConfig();			
+		}
+		
+		private function spellCheckScreen(event:Event):void
+		{
+			doSpellingJob();
+		}
+		
+				
+		/**
+		 @private
+		 (This property is for Squiggly Developer use only.)
+		 */		
+		public function doSpellingJob():void
+		{
+			if (_spellingEnabled == false) return;
+			
+			hh.clearSquiggles();
+			for (var idx:int = 0; idx < mTextFlow.flowComposer.numControllers; idx++)
+			{
+				var testController:ContainerController = mTextFlow.flowComposer.getControllerAt(idx); 
+				//if (getValidFirstWordIndexTLF(testController) != -1) 
+				spellCheckRangeTLF(getValidFirstWordIndexTLF(testController), getValidLastWordIndexTLF(testController));
+			}
+			
+		}
+			
+		
+		private function spellCheckRangeTLF(start:uint, end:uint):void {
+			var tokenizer:TextTokenizer;
+			//hh.clearSquiggles();
+			var tt:TextFlow = mTextFlow;
+			//var currentLeaf:FlowLeafElement = tt.getFirstLeaf();
+			var currentLeaf:FlowLeafElement = tt.findLeaf(start);
+			var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null;
+			while (currentParagraph) { // iterate over all paragraphs in the text flow
+				var paraStart:uint = currentParagraph.getAbsoluteStart();
+				if (paraStart > end)
+					break; 
+				
+				//var offsetPoint:Point = new Point(currentParagraph.paddingLeft, currentParagraph.paddingTop); 
+				//hh.offsetPoint = offsetPoint;
+				tokenizer = new TextTokenizer(currentParagraph.getText().substring());
+				//var tokens:Vector.<Token> = new Vector.<Token>();
+				var currentWord:String;
+				var filteredWord:String;
+				for ( var token:Token = tokenizer.getFirstToken(); token != tokenizer.getLastToken(); token= tokenizer.getNextToken(token) ) {
+					currentWord= currentParagraph.getText().substring(token.first, token.last);
+					filteredWord= _textFilter.filterWord(currentWord);
+					var result:Boolean=_spellingservice.checkWord(filteredWord);					
+					if (!result){
+						//if (_checkLastWord || (token.last+paraStart != currentParagraph.getText().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+paraStart, token.last+paraStart-1));
+					}
+					
+				}
+				currentParagraph = currentParagraph.getNextParagraph();
+				
+			}
+			//hh.postSpellCheckRange(start, end);
+			//hh.offsetPoint = offsetPoint;
+			//hh.drawSquiggles(tokens);
+		}
+		private function getValidFirstWordIndexTLF(containerController:ContainerController):int{			
+			var index:int;
+					
+			// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+			try {
+				//index = SelectionManager.computeSelectionIndex(mTextFlow, containerController.container, containerController.container, 0 + containerController.horizontalScrollPosition, 0 + containerController.verticalScrollPosition);
+				// SelectionManager.computeSelectionIndex() sometimes gives index as -1. in the same scenarios below logic works better 
+				var tl:TextFlowLine = containerController.getFirstVisibleLine();
+				var firstVisiblePosition:int = tl.absoluteStart;
+				index = firstVisiblePosition;
+								
+			} catch (err:Error)
+			{
+				//TODO: report error
+				index = 0;
+			}
+				
+			return index;
+		}
+		
+		private function getValidLastWordIndexTLF(containerController:ContainerController):int{			
+			var index:int;
+			
+			// Check for computeSelectionIndexInContainer which throws when lineindex == 0
+			try {
+				//index = SelectionManager.computeSelectionIndex(mTextFlow, containerController.container, containerController.container, containerController.container.width+containerController.horizontalScrollPosition, containerController.container.height+containerController.verticalScrollPosition);
+				var tl:TextFlowLine = containerController.getLastVisibleLine();
+				var lastVisiblePosition:int = tl.absoluteStart + tl.textLength;
+				index = lastVisiblePosition;
+			} catch (err:Error)
+			{
+				//TODO: report error
+				index = 0;
+			}
+				
+			return index;
+		}
+		
+
+		private function loadConfig():void{
+			_thirdPatyResourceLocation = SpellingConfiguration.resourceTable.thirdPatyResourceLocation;
+			
+			if ((_thirdPatyResourceLocation != null) || (SpellUIForTLF._configXML != null)) 
+				loadConfigComplete(null);
+			else {	
+				SpellUIForTLF._configXMLLoader.addEventListener(Event.COMPLETE, loadConfigComplete);
+			
+				if (SpellUIForTLF._configXMLLoading == false)
+				{
+					SpellUIForTLF._configXMLLoader.load(new URLRequest(_spellingConfigUrl));
+					SpellUIForTLF._configXMLLoading = true;
+				}
+			}
+		}
+		
+		private function loadConfigComplete(evt:Event):void{
+			if (_thirdPatyResourceLocation == null) {
+			if (SpellUIForTLF._configXML == null)
+				SpellUIForTLF._configXML= new XML(evt.target.data);
+			
+				SpellingConfiguration.resourceTable.thirdPatyResourceLocation=SpellUIForTLF._configXML.ThirdPartyResourceLocation.@URL;
+		}
+                //New Added
+			_spellingservice = new SpellingService(_dictname);
+			_spellingservice.thirdPatyResourceLocation=SpellingConfiguration.resourceTable.thirdPatyResourceLocation;
+			_spellingservice.addEventListener(Event.COMPLETE, loadDictComplete);
+			_spellingservice.init();
+		}
+		
+				
+				
+		
+		private function loadDictComplete(evt:Event):void
+		{					
+			//_newchecker = new SpellChecker(_hundict);
+			
+			// Lazy loading the UD only when the main dict is loaded successfully
+			if ((SpellUIForTLF._cache["Squiggly_UD"] as UserDictionary) == null)
+			{
+				_sharedobj = SharedObject.getLocal("Squiggly_Muse");
+				var udMap:Dictionary = new Dictionary();
+				//var vec:Vector.<String> = new Vector.<String>();
+				if (_sharedobj.data.udMap) 
+					_userdict = new UserDictionary(_sharedobj.data.udMap as Array);
+				
+				SpellUIForTLF._cache["Squiggly_SO"] = _sharedobj;
+				SpellUIForTLF._cache["Squiggly_UD"] = _userdict;
+			}
+			else 
+			{
+				_sharedobj = SpellUIForTLF._cache["Squiggly_SO"];
+				_userdict = SpellUIForTLF._cache["Squiggly_UD"];
+			}
+			_spellingservice.addUserDictionary(_userdict);
+			
+			
+			// Add the context menu, this might be not successful
+			/*Removing scm*/
+	//-->		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;
+			
+			hh = new TLFHighlighter( _actualParent);
+			hw = new TLFWordProcessor( _actualParent);	
+						
+	//-->		scm =  new SpellingContextMenuForTLF(hh, hw, _spellingservice, _actualParent, addWordToUserDictionary); 
+			//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, language:String):void
+		{
+			if(_userdict==null)
+			{
+				_userdict=new UserDictionary();
+				_spellingservice.addUserDictionary(_userdict);
+			}
+			_userdict.addWord(_textFilter.filterWord(word),language);
+		
+			// TODO: serialization here might affect ther performance
+			_sharedobj.data.udMap = _userdict.wordListMap as Array;
+			
+		}
+		
+		private function removeWordFromUserDictionary(word:String, language:String):void
+		{
+			if(_userdict==null)
+				return;
+			_userdict.removeWord(_textFilter.filterWord(word),language);
+			
+			// TODO: serialization here might affect ther performance
+			_sharedobj.data.udMap = _userdict.wordListMap;
+			
+		}
+		
+		private function getUDWordListForLanguage(language:String):Array
+		{
+			if(_userdict==null || _userdict.getWordList(language)==null)
+				return null;
+			else
+				return	_userdict.getWordList(language).toArray();
+			
+		}
+		/**
+		 *	@private
+		 */
+		private function cleanUp():void {
+			hh.clearSquiggles();
+	//-->		scm.cleanUp();
+	//-->		_actualParent.removeEventListener(Event.ADDED_TO_STAGE, addContextMenu);
+			
+			//mTextFlow.removeEventListener(flashx.textLayout.events.CompositionCompleteEvent.COMPOSITION_COMPLETE, spellCheckScreen);
+			mTextFlow.removeEventListener(flashx.textLayout.events.UpdateCompleteEvent.UPDATE_COMPLETE, spellCheckScreen);
+			//mTextFlow.removeEventListener(flashx.textLayout.events.StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, spellCheckScreen);
+		}
+		
+		//retuns the Highlighter object for this text flow
+		public static function getHighlighter(textFlow:TextFlow):IHighlighter{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj.hh;
+		}
+		
+		//return the WordProcessor Object for this text flow
+		public static function getWordProcessor(textFlow:TextFlow):IWordProcessor{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj.hw;
+		}
+		
+		//return the SpellingService Object for this text flow
+		public static function getSpellingService(textFlow:TextFlow):SpellingService{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj._spellingservice;
+		}
+		//return the SpellingService Object for this text flow
+		public static function getAddToDictionaryFunction(textFlow:TextFlow):Function{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj.addWordToUserDictionary;
+		}
+		
+		public static function getRemoveFromDictionaryFunction(textFlow:TextFlow):Function{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj.removeWordFromUserDictionary;
+		}
+		
+		public static function getWordListFunction(textFlow:TextFlow):Function{
+			var spellUIObj:SpellUIForTLF= _UITable[textFlow];
+			return spellUIObj.getUDWordListForLanguage;
+		}
+		
+	}
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IHighlighter.as b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IHighlighter.as
new file mode 100644
index 0000000..20c46b7
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/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/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
new file mode 100644
index 0000000..22e9cc9
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/IWordProcessor.as
@@ -0,0 +1,32 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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;
+	import flashx.textLayout.container.ContainerController;
+	
+	public interface IWordProcessor
+	{
+		function getWordAtPoint(x:uint, y:uint, externalTokenizer:ITokenizer=null):Token;
+		function replaceText(token:Token, replacement:String):void;
+		function set textFlowContainerController(value:ContainerController):void;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFHighlighter.as
new file mode 100644
index 0000000..3c8c7e9
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/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/a52655ac/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
new file mode 100644
index 0000000..8cb3197
--- /dev/null
+++ b/Squiggly/ane/Squiggly/AdobeSpellingUITLF/src/com/adobe/linguistics/spelling/ui/TLFWordProcessor.as
@@ -0,0 +1,164 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+* Author (U)  Ravi Singh (ravi@adobe.com) 
+* Created  12/08/2010
+*/
+
+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/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/SimpleText.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/SimpleText.xml b/Squiggly/ane/Squiggly/Demo/SimpleEditor/SimpleText.xml
new file mode 100644
index 0000000..3428b0d
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/SimpleText.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+  <flow:TextFlow xmlns:flow="http://ns.adobe.com/textLayout/2008" fontSize="14" textIndent="15" paragraphSpaceAfter="15" paddingTop="4" paddingLeft="4">
+    <flow:p><flow:span>There's There’s lime-kiln lime‑kiln lime‐kiln There are many </flow:span><flow:span fontStyle="italic">such</flow:span><flow:span> lime-kilns in that tract of country, for the purpose of burning the white marble which composes a large part of the substance of the hills. Some of them, built years ago, and long deserted, with weeds growing in the vacant round of the interior, which is open to the sky, and grass and wild-flowers rooting themselves into the chinks of the stones, look already like relics of antiquity, and may yet be overspread with the lichens of centuries to come. Others, where the lime-burner still feeds his daily and nightlong fire, afford points of interest to the wanderer among the hills, who seats himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. It is a lonesome, and, when the character is inclined to thought, may be an intensely thoughtful occupation; as it proved in the case of Ethan Brand, who h
 ad mused to such strange purpose, in days gone by, while the fire in this very kiln was burning.</flow:span></flow:p>
+	<flow:p><flow:span>The man who now watched the fire was of a different order, and troubled himself with no thoughts save the very few that were requisite to his business. At frequent intervals, he flung back the clashing weight of the iron door, and, turning his face from the insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a long pole. Within the furnace were seen the curling and riotous flames, and the burning marble, almost molten with the intensity of heat; while without, the reflection of the fire quivered on the dark intricacy of the surrounding forest, and showed in the foreground a bright and ruddy little picture of the hut, the spring beside its door, the athletic and coal-begrimed figure of the lime-burner, and the half-frightened child, shrinking into the protection of his father's shadow. And when again the iron door was closed, then reappeared the tender light of the half-full moon, which vainly strove to trace out the indistinct shape
 s of the neighboring mountains; and, in the upper sky, there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, though thus far down into the valley the sunshine had vanished long and long ago.</flow:span></flow:p>
+  </flow:TextFlow>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/AdobeSpellingConfig.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/AdobeSpellingConfig.xml b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/AdobeSpellingConfig.xml
new file mode 100644
index 0000000..19c97ba
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/AdobeSpellingConfig.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding='UTF-8'?>
+<!--
+
+  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.
+
+-->
+<SpellingConfig>
+  <ThirdPartyResourceLocation URL="D:\\Program Files\\Common Files\\adobe\\linguistics\\ThirdPartyResources" />
+</SpellingConfig>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/MyContainerController.as
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/MyContainerController.as b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/MyContainerController.as
new file mode 100644
index 0000000..cd37d3c
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/MyContainerController.as
@@ -0,0 +1,300 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 {
+	import com.adobe.linguistics.spelling.SpellUIForTLF;
+	import com.adobe.linguistics.spelling.framework.SpellingService;
+	import com.adobe.linguistics.spelling.ui.IHighlighter;
+	import com.adobe.linguistics.spelling.ui.IWordProcessor;
+	import com.adobe.linguistics.spelling.ui.TLFWordProcessor;
+	import com.adobe.linguistics.utils.TextFilter;
+	import com.adobe.linguistics.utils.Token;
+	import flash.net.SharedObject;
+	import flash.display.Sprite;
+	import flash.events.ContextMenuEvent;
+	import flash.ui.ContextMenu;
+	import flash.ui.ContextMenuItem;
+	
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.conversion.TextConverter;
+	import flashx.textLayout.edit.IEditManager;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.undo.IUndoManager;
+	
+	class MyContainerController extends ContainerController
+	{
+
+		public function MyContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100)
+		{
+			super (container, compositionWidth, compositionHeight);
+			spellingEnabled=false;
+			_textFilter= new TextFilter();
+		}
+		
+		/** Overridden to add custom items to the context menu */
+		override protected function createContextMenu():ContextMenu
+		{
+			// Get the default context menu used by TLF for editable flows
+			contextMenu= super.createContextMenu();
+			
+			// Listen for menu selection
+			contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, updateCustomMenuItems);
+			
+			// Add custom menu items
+			_undoItem = new ContextMenuItem("[Undo]"); // for illustration only; not "undo" caption is not allowed 
+			_undoItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, undo);
+			contextMenu.customItems.push(_undoItem);
+			
+			_redoItem = new ContextMenuItem("[Redo]");
+			_redoItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, redo);
+			contextMenu.customItems.push(_redoItem);
+			
+			_enableSpelling= new ContextMenuItem("[Enable Spelling]");
+			_enableSpelling.visible=!spellingEnabled;
+			_enableSpelling.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, enableSpelling);
+			contextMenu.customItems.push(_enableSpelling);
+			
+			_disableSpelling= new ContextMenuItem("[Disable Spelling]");
+			_disableSpelling.visible=spellingEnabled;
+			_disableSpelling.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, disableSpelling);
+			contextMenu.customItems.push(_disableSpelling);
+			
+			return contextMenu;
+		}
+		
+		/** Update the state of the custom menu items before the context menu is displayed */
+		private function updateCustomMenuItems(event:ContextMenuEvent):void 
+		{
+			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");
+			}
+			
+			var undoManager:IUndoManager = (textFlow.interactionManager as IEditManager).undoManager;
+			_undoItem.enabled = undoManager.canUndo();
+			_redoItem.enabled = undoManager.canRedo();
+			//-->>>
+			if(!SpellUIForTLF.UITable[textFlow])
+			{
+				spellingEnabled=false;
+				updateVisibility();
+			}
+			else
+			{
+				spellingEnabled= SpellUIForTLF.UITable[textFlow].spellingEnabled;
+				updateVisibility();
+				if(!mWordProcessor)
+					mWordProcessor=SpellUIForTLF.getWordProcessor(textFlow);
+				if(!mSpellEngine)
+					mSpellEngine=SpellUIForTLF.getSpellingService(textFlow);
+				if(!mAddToDictionaryFunction)
+					mAddToDictionaryFunction= SpellUIForTLF.getAddToDictionaryFunction(textFlow);
+				if(!mRemoveFromDictionaryFunction)
+					mRemoveFromDictionaryFunction= SpellUIForTLF.getRemoveFromDictionaryFunction(textFlow);
+				if(!mGetWordListFunction)
+					mGetWordListFunction=SpellUIForTLF.getWordListFunction(textFlow);
+				if(mWordProcessor==null || mSpellEngine==null) 
+					return;
+				  migrateWordsR4();
+				(mWordProcessor as TLFWordProcessor).textFlowContainerController = this;
+					
+					//trace("stageX " +  super.container.stage.mouseX);
+					//trace("stageY " +  super.container.stage.mouseY);
+					//trace("mouseX " +  super.container.mouseX);
+					//trace("mouseY " +  super.container.mouseY);
+					_misspelledToken = mWordProcessor.getWordAtPoint(this.container.mouseX, this.container.mouseY);
+					if (_misspelledToken==null) return;
+					var currentLeaf:FlowLeafElement = this.textFlow.findLeaf(_misspelledToken.first);
+					var currentParagraph:ParagraphElement = currentLeaf ? currentLeaf.getParagraph() : null;
+					_misspelled = currentParagraph?	currentParagraph.getText().substring(_misspelledToken.first - currentParagraph.getAbsoluteStart(), 
+						_misspelledToken.last - currentParagraph.getAbsoluteStart()) : null;
+					if ((_misspelled==null) || (_misspelled == "")) return;
+					
+					_filteredMisspelled= _textFilter.filterWord(_misspelled);
+					if (mSpellEngine.checkWord(_filteredMisspelled)==true) return;				
+					
+					var suseAddToItem:ContextMenuItem = new ContextMenuItem("[Add to Dictionary]");
+					suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleAddToItemSelect);
+					suggestionMenuItemList.push(suseAddToItem);
+					contextMenu.customItems.splice(0,0,suseAddToItem);	
+					
+					suseAddToItem = new ContextMenuItem("[Add to AllLang Dictionary]");
+					suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, handleAddAllLanguageWords);
+					suggestionMenuItemList.push(suseAddToItem);
+					contextMenu.customItems.splice(0,0,suseAddToItem);
+					
+					suseAddToItem = new ContextMenuItem("[Remove Word]");
+					suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, removeWord);
+					suggestionMenuItemList.push(suseAddToItem);
+					contextMenu.customItems.splice(0,0,suseAddToItem);
+					
+					
+					suseAddToItem = new ContextMenuItem("[Trace All Words]");
+					suseAddToItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, printTraces);
+					suggestionMenuItemList.push(suseAddToItem);
+					contextMenu.customItems.splice(0,0,suseAddToItem);	
+					
+					//var result:Array = mWordProcessor.getSuggestionsAtPoint();
+					var resultVector:Vector.<String> = mSpellEngine.getSuggestions(_filteredMisspelled);
+					var result:Array = new Array();
+					if (resultVector) {
+						for each (var w:String in resultVector)
+						{
+							if(w.length >3) result.push(toInitCap(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);
+						}
+					}
+			}
+				//--->
+		}
+		
+		private function undo(event:ContextMenuEvent):void 
+		{
+			(textFlow.interactionManager as IEditManager).undoManager.undo();
+		}
+		
+		private function redo(event:ContextMenuEvent):void 
+		{
+			(textFlow.interactionManager as IEditManager).undoManager.redo();
+		}
+		
+		private function enableSpelling(event:ContextMenuEvent):void{
+			SpellUIForTLF.enableSpelling(textFlow,_language);//TODO: Pass language from main application here...remove hard code
+			spellingEnabled= SpellUIForTLF.UITable[textFlow].spellingEnabled;
+			updateVisibility();
+		}
+		
+		private function disableSpelling(event:ContextMenuEvent):void{
+			SpellUIForTLF.disableSpelling(textFlow);
+			setFuncsNull();
+			spellingEnabled= false;
+			updateVisibility();
+		}
+		private function updateVisibility():void{
+			_enableSpelling.visible=!spellingEnabled;
+			_disableSpelling.visible=spellingEnabled;
+		}
+		
+		private function handleAddToItemSelect(event:ContextMenuEvent):void{
+			mAddToDictionaryFunction(_misspelled,_language);
+			
+		}
+		
+
+		
+		private function printTraces(event:ContextMenuEvent):void{
+			var arr:Array=mGetWordListFunction(_language);
+			if(!arr) return;
+			for each( var k:String in arr)
+				trace(k);
+		}
+		
+		private function removeWord(event:ContextMenuEvent):void{
+			mRemoveFromDictionaryFunction("woodoo",_language);
+		}
+		private function handleSuseItemSelect(event:ContextMenuEvent):void
+		{
+			mWordProcessor.replaceText(_misspelledToken, (event.currentTarget as ContextMenuItem).caption );
+			SpellUIForTLF.UITable[textFlow].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 toInitCap(w:String):String{
+			return w.substr(0,1).toLocaleUpperCase()+w.substr(1);
+		}
+		private function handleAddAllLanguageWords(event:ContextMenuEvent):void{
+			mAddToDictionaryFunction(_misspelled,"lang_neutral");
+		}
+		
+		public function get language():String
+		{
+			return _language;
+		}
+		
+		public function set language(value:String):void
+		{
+			_language = value;
+		}
+		public function setFuncsNull():void
+		{
+			mAddToDictionaryFunction=null;
+			mSpellEngine=null;
+			mHighlighter=null;
+			mGetWordListFunction=null;
+			mRemoveFromDictionaryFunction=null;
+			mWordProcessor=null;
+		}
+		
+		private function migrateWordsR4():void{
+			var sharedObjectOld:SharedObject= SharedObject.getLocal("Squiggly_v03");
+			var vec:Vector.<String> = new Vector.<String>();
+			if (sharedObjectOld.data.ud) {
+				for each (var w:String in sharedObjectOld.data.ud)
+				mAddToDictionaryFunction(w, "lang_neutral");
+			}
+		}
+		private var _undoItem:ContextMenuItem;
+		private var _redoItem:ContextMenuItem;
+		private var _enableSpelling:ContextMenuItem;
+		private var _disableSpelling:ContextMenuItem;
+		private var mHighlighter:IHighlighter =null;
+		private var mWordProcessor:IWordProcessor=null;
+		private var mSpellEngine:SpellingService= null;
+		private var mAddToDictionaryFunction:Function=null;
+		private var mRemoveFromDictionaryFunction:Function=null;
+		private var mGetWordListFunction:Function=null;
+		private var _misspelledToken:Token=null;
+		private var _misspelled:String;
+		private var _filteredMisspelled:String;
+		private var suggestionMenuItemList:Array = new Array();
+		private var contextMenu:ContextMenu=null;
+		private var spellingEnabled:Boolean;
+		private var _textFilter:TextFilter=null;
+		private var _language:String;
+		
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor-app.xml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor-app.xml b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor-app.xml
new file mode 100644
index 0000000..df4187e
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor-app.xml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<!--
+
+  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.
+
+-->
+<application xmlns="http://ns.adobe.com/air/application/3.1">
+
+<!-- Adobe AIR Application Descriptor File Template.
+
+	Specifies parameters for identifying, installing, and launching AIR applications.
+
+	xmlns - The Adobe AIR namespace: http://ns.adobe.com/air/application/3.1
+			The last segment of the namespace specifies the version 
+			of the AIR runtime required for this application to run.
+			
+	minimumPatchLevel - The minimum patch level of the AIR runtime required to run 
+			the application. Optional.
+-->
+
+	<!-- A universally unique application identifier. Must be unique across all AIR applications.
+	Using a reverse DNS-style name as the id is recommended. (Eg. com.example.ExampleApplication.) Required. -->
+	<id>SimpleEditor</id>
+
+	<!-- Used as the filename for the application. Required. -->
+	<filename>SimpleEditor</filename>
+
+	<!-- The name that is displayed in the AIR application installer. 
+	May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<name>SimpleEditor</name>
+	
+	<!-- A string value of the format <0-999>.<0-999>.<0-999> that represents application version which can be used to check for application upgrade. 
+	Values can also be 1-part or 2-part. It is not necessary to have a 3-part value.
+	An updated version of application must have a versionNumber value higher than the previous version. Required for namespace >= 2.5 . -->
+	<versionNumber>0.0.0</versionNumber>
+		         
+	<!-- A string value (such as "v1", "2.5", or "Alpha 1") that represents the version of the application, as it should be shown to users. Optional. -->
+	<!-- <versionLabel></versionLabel> -->
+
+	<!-- Description, displayed in the AIR application installer.
+	May have multiple values for each language. See samples or xsd schema file. Optional. -->
+	<!-- <description></description> -->
+
+	<!-- Copyright information. Optional -->
+	<!-- <copyright></copyright> -->
+
+	<!-- Publisher ID. Used if you're updating an application created prior to 1.5.3 -->
+	<!-- <publisherID></publisherID> -->
+
+	<!-- Settings for the application's initial window. Required. -->
+	<initialWindow>
+		<!-- The main SWF or HTML file of the application. Required. -->
+		<!-- Note: In Flash Builder, the SWF reference is set automatically. -->
+		<content>[This value will be overwritten by Flash Builder in the output app.xml]</content>
+		
+		<!-- The title of the main window. Optional. -->
+		<!-- <title></title> -->
+
+		<!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
+		<!-- <systemChrome></systemChrome> -->
+
+		<!-- Whether the window is transparent. Only applicable when systemChrome is none. Optional. Default false. -->
+		<!-- <transparent></transparent> -->
+
+		<!-- Whether the window is initially visible. Optional. Default false. -->
+		<!-- <visible></visible> -->
+
+		<!-- Whether the user can minimize the window. Optional. Default true. -->
+		<!-- <minimizable></minimizable> -->
+
+		<!-- Whether the user can maximize the window. Optional. Default true. -->
+		<!-- <maximizable></maximizable> -->
+
+		<!-- Whether the user can resize the window. Optional. Default true. -->
+		<!-- <resizable></resizable> -->
+
+		<!-- The window's initial width in pixels. Optional. -->
+		<!-- <width></width> -->
+
+		<!-- The window's initial height in pixels. Optional. -->
+		<!-- <height></height> -->
+
+		<!-- The window's initial x position. Optional. -->
+		<!-- <x></x> -->
+
+		<!-- The window's initial y position. Optional. -->
+		<!-- <y></y> -->
+
+		<!-- The window's minimum size, specified as a width/height pair in pixels, such as "400 200". Optional. -->
+		<!-- <minSize></minSize> -->
+
+		<!-- The window's initial maximum size, specified as a width/height pair in pixels, such as "1600 1200". Optional. -->
+		<!-- <maxSize></maxSize> -->
+
+        <!-- The initial aspect ratio of the app when launched (either "portrait" or "landscape"). Optional. Mobile only. Default is the natural orientation of the device -->
+
+        <!-- <aspectRatio></aspectRatio> -->
+
+        <!-- Whether the app will begin auto-orienting on launch. Optional. Mobile only. Default false -->
+
+        <!-- <autoOrients></autoOrients> -->
+
+        <!-- Whether the app launches in full screen. Optional. Mobile only. Default false -->
+
+        <!-- <fullScreen></fullScreen> -->
+
+        <!-- The render mode for the app (either auto, cpu, gpu, or direct). Optional. Default auto -->
+
+        <!-- <renderMode></renderMode> -->
+
+		<!-- Whether or not to pan when a soft keyboard is raised or lowered (either "pan" or "none").  Optional.  Defaults "pan." -->
+		<!-- <softKeyboardBehavior></softKeyboardBehavior> -->
+	<autoOrients>false</autoOrients>
+        <fullScreen>false</fullScreen>
+        <visible>false</visible>
+    </initialWindow>
+
+	<!-- We recommend omitting the supportedProfiles element, -->
+	<!-- which in turn permits your application to be deployed to all -->
+	<!-- devices supported by AIR. If you wish to restrict deployment -->
+	<!-- (i.e., to only mobile devices) then add this element and list -->
+	<!-- only the profiles which your application does support. -->
+	<!-- <supportedProfiles>desktop extendedDesktop mobileDevice extendedMobileDevice</supportedProfiles> -->
+	<supportedProfiles>desktop extendedDesktop </supportedProfiles>
+	<!-- The subpath of the standard default installation location to use. Optional. -->
+	<!-- <installFolder></installFolder> -->
+
+	<!-- The subpath of the Programs menu to use. (Ignored on operating systems without a Programs menu.) Optional. -->
+	<!-- <programMenuFolder></programMenuFolder> -->
+
+	<!-- The icon the system uses for the application. For at least one resolution,
+	specify the path to a PNG file included in the AIR package. Optional. -->
+	<!-- <icon>
+		<image16x16></image16x16>
+		<image32x32></image32x32>
+		<image36x36></image36x36>
+		<image48x48></image48x48>
+		<image57x57></image57x57>
+		<image72x72></image72x72>
+		<image114x114></image114x114>
+		<image128x128></image128x128>
+	</icon> -->
+
+	<!-- Whether the application handles the update when a user double-clicks an update version
+	of the AIR file (true), or the default AIR application installer handles the update (false).
+	Optional. Default false. -->
+	<!-- <customUpdateUI></customUpdateUI> -->
+	
+	<!-- Whether the application can be launched when the user clicks a link in a web browser.
+	Optional. Default false. -->
+	<!-- <allowBrowserInvocation></allowBrowserInvocation> -->
+
+	<!-- Listing of file types for which the application can register. Optional. -->
+	<!-- <fileTypes> -->
+
+		<!-- Defines one file type. Optional. -->
+		<!-- <fileType> -->
+
+			<!-- The name that the system displays for the registered file type. Required. -->
+			<!-- <name></name> -->
+
+			<!-- The extension to register. Required. -->
+			<!-- <extension></extension> -->
+			
+			<!-- The description of the file type. Optional. -->
+			<!-- <description></description> -->
+			
+			<!-- The MIME content type. -->
+			<!-- <contentType></contentType> -->
+			
+			<!-- The icon to display for the file type. Optional. -->
+			<!-- <icon>
+				<image16x16></image16x16>
+				<image32x32></image32x32>
+				<image48x48></image48x48>
+				<image128x128></image128x128>
+			</icon> -->
+			
+		<!-- </fileType> -->
+	<!-- </fileTypes> -->
+
+    <!-- iOS specific capabilities -->
+	<!-- <iPhone> -->
+		<!-- A list of plist key/value pairs to be added to the application Info.plist -->
+		<!-- <InfoAdditions>
+            <![CDATA[
+                <key>UIDeviceFamily</key>
+                <array>
+                    <string>1</string>
+                    <string>2</string>
+                </array>
+                <key>UIStatusBarStyle</key>
+                <string>UIStatusBarStyleBlackOpaque</string>
+                <key>UIRequiresPersistentWiFi</key>
+                <string>YES</string>
+            ]]>
+        </InfoAdditions> -->
+        <!-- A list of plist key/value pairs to be added to the application Entitlements.plist -->
+		<!-- <Entitlements>
+            <![CDATA[
+                <key>keychain-access-groups</key>
+                <array>
+                    <string></string>
+                    <string></string>
+                </array>
+            ]]>
+        </Entitlements> -->
+	<!-- Display Resolution for the app (either "standard" or "high"). Optional. Default "standard" -->
+	<!-- <requestedDisplayResolution></requestedDisplayResolution> -->
+	<!-- </iPhone> -->
+
+	<!-- Specify Android specific tags that get passed to AndroidManifest.xml file. -->
+    <!--<android> -->
+    <!--	<manifestAdditions>
+		<![CDATA[
+			<manifest android:installLocation="auto">
+				<uses-permission android:name="android.permission.INTERNET"/>
+				<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+				<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+				<uses-feature android:required="true" android:name="android.hardware.touchscreen.multitouch"/>
+				<application android:enabled="true">
+					<activity android:excludeFromRecents="false">
+						<intent-filter>
+							<action android:name="android.intent.action.MAIN"/>
+							<category android:name="android.intent.category.LAUNCHER"/>
+						</intent-filter>
+					</activity>
+				</application>
+            </manifest>
+		]]>
+        </manifestAdditions> -->
+	    <!-- Color depth for the app (either "32bit" or "16bit"). Optional. Default 16bit before namespace 3.0, 32bit after -->
+        <!-- <colorDepth></colorDepth> -->
+    <!-- </android> -->
+	<!-- End of the schema for adding the android specific tags in AndroidManifest.xml file -->
+
+<extensions>
+        <extensionID>com.adobe.linguistics.extensions.HunspellNativeExtension</extensionID>
+    </extensions>
+</application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor.mxml b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor.mxml
new file mode 100644
index 0000000..1876e3e
--- /dev/null
+++ b/Squiggly/ane/Squiggly/Demo/SimpleEditor/src/SimpleEditor.mxml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+
+
+<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="100%" height="100%" initialize="init()" resize="handleResize()" horizontalScrollPolicy="off" verticalScrollPolicy="off" xmlns:local="*" backgroundColor="#FFFFFF">
+	<!-- This file loads and parses a TextFlow markup file and attaches it to the SimpleEditorPanel  -->
+	<mx:Script>
+		<![CDATA[
+			import flashx.textLayout.elements.TextFlow;
+			import flashx.textLayout.conversion.TextConverter;
+			
+			import flash.events.Event;
+			import flash.events.IOErrorEvent;
+			
+			
+			static private const simpleText:String = "<TextFlow xmlns='http://ns.adobe.com/textLayout/2008' fontSize='14' textIndent='15' marginBottom='15' paddingTop='4' paddingLeft='4'>"
+   				+ "<p><span>There are many </span><span fontStyle='italic'>such</span><span> lime-kilns in that tract of country, for the purpose of burning the white marble which composes a large part of the substance of the hills. Some of them, built years ago, and long deserted, with weeds growing in the vacant round of the interior, which is open to the sky, and grass and wild-flowers rooting themselves into the chinks of the stones, look already like relics of antiquity, and may yet be overspread with the lichens of centuries to come. Others, where the lime-burner still feeds his daily and nightlong fire, afford points of interest to the wanderer among the hills, who seats himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. It is a lonesome, and, when the character is inclined to thought, may be an intensely thoughtful occupation; as it proved in the case of Ethan Brand, who had mused to such strange purpose, in days gone by, while the fire in this ve
 ry kiln was burning.</span></p>"
+				+ "<p><span>The man who now watched the fire was of a different order, and troubled himself with no thoughts save the very few that were requisite to his business. At frequent intervals, he flung back the clashing weight of the iron door, and, turning his face from the insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a long pole. Within the furnace were seen the curling and riotous flames, and the burning marble, almost molten with the intensity of heat; while without, the reflection of the fire quivered on the dark intricacy of the surrounding forest, and showed in the foreground a bright and ruddy little picture of the hut, the spring beside its door, the athletic and coal-begrimed figure of the lime-burner, and the half-frightened child, shrinking into the protection of his father's shadow. And when again the iron door was closed, then reappeared the tender light of the half-full moon, which vainly strove to trace out the indistinct shapes of
  the neighboring mountains; and, in the upper sky, there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, though thus far down into the valley the sunshine had vanished long and long ago.</span></p>"
+ 				+ "</TextFlow>";
+			
+			/** Initialize the application */
+			private function init():void
+			{
+				// adjust the selection color when focus is not on the selection to look the same.  
+				// This is appropriate for an editor but not for UI widgets
+				TextFlow.defaultConfiguration.unfocusedSelectionFormat = TextFlow.defaultConfiguration.focusedSelectionFormat;
+				
+				// switch the boolean below to read the file at run time.  Note: you have to add the swf to the trusted list to load a local file
+				if (false)
+				{
+					// Initiate read of a file
+					var loader:URLLoader = new URLLoader();
+					loader.load(new URLRequest("../SimpleText.xml"));	// for example
+					loader.addEventListener(Event.COMPLETE,loadCompleteHandler);	
+					loader.addEventListener(IOErrorEvent.IO_ERROR,errorHandler);
+				}
+				else
+				{		
+					editor.textFlow = TextConverter.importToFlow(simpleText, TextConverter.TEXT_LAYOUT_FORMAT);
+				}
+				handleResize();
+			}
+			
+			/** on file load error show the error string */
+			private function errorHandler(e:IOErrorEvent):void
+			{
+				editor.textFlow = TextConverter.importToFlow("\n"+IOErrorEvent(e).text, TextConverter.PLAIN_TEXT_FORMAT);
+			}
+			/** on success parse the file and display it */
+			private function loadCompleteHandler(e:Event):void
+			{
+		 		editor.textFlow = TextConverter.importToFlow(e.target.data, TextConverter.TEXT_LAYOUT_FORMAT);
+			}
+			
+			/** Update the size of the editor to be the full size of this window */
+			private function handleResize():void
+			{
+				if (editor)
+					editor.setSize(this.width,this.height);
+			}
+		]]>
+	</mx:Script>
+	<local:SimpleEditorPanel id="editor"/>
+
+</mx:WindowedApplication>


[13/18] Squiggly spell checker donation from Adobe Systems Inc.

Posted by ah...@apache.org.
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
new file mode 100644
index 0000000..d628280
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Air/UserDictionaryExample/src/UserDictionaryExample.mxml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!---
+* @exampleText The following UserDictionaryExample MXML demonstrates how to use the Squiggly user dictionary API to add/remove words and to save to/load from a file.
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingEngine.swc) in your libs folder. It must be an AIR project for the File class to work.
+-->
+<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" horizontalAlign="left" initialize="init()">
+<mx:Script>
+	<![CDATA[
+
+
+	import com.adobe.linguistics.spelling.HunspellDictionary;
+	import com.adobe.linguistics.spelling.SpellChecker;
+	import com.adobe.linguistics.spelling.UserDictionary;
+		
+	
+	private var ud:UserDictionary;
+	private var _newdict:HunspellDictionary = new HunspellDictionary();
+	private var sp:SpellChecker;
+	private function init():void {
+		_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+		_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+	}
+		
+	private function handleLoadComplete(evt:Event):void
+	{
+		sp = new SpellChecker(_newdict);
+	}
+
+	private function checkWord():void {
+		if( sp.checkWord( inputWord.text ) )
+			result.text = "Result:correct";
+		else
+			result.text = "Result:wrong";
+	}
+		
+	public function updateWordList():void
+	{
+		wordList.text = "";
+		
+		var wl:Vector.<String> = ud.wordList;
+		for each(var w:String in wl)
+		{
+			wordList.text += w + "\n";
+		}
+		
+	}
+	
+	
+	public function loadDict():void
+	{
+		var inFile:File = File.desktopDirectory;
+		inFile = inFile.resolvePath(filename.text);
+		if (inFile.exists)
+		{		
+			var inStream:FileStream = new FileStream();
+			inStream.open(inFile, FileMode.READ);
+			ud = new UserDictionary(inStream.readObject() as Vector.<String>);
+			inStream.close();  	
+			result1.text = "File loaded";	
+		}
+		else
+		{
+			ud = new UserDictionary();
+			result1.text = "File created";
+		}		
+		updateWordList();
+		sp.addUserDictionary(ud);
+	}
+	
+	public function saveDict():void
+	{
+		var outFile:File = File.desktopDirectory;
+		outFile = outFile.resolvePath(filename.text);
+		var outStream:FileStream = new FileStream();
+		outStream.open(outFile, FileMode.WRITE);
+		outStream.writeObject(ud.wordList);
+		outStream.close();
+		result1.text = "File saved"
+	}
+	
+	public function addWord():void
+	{
+		ud.addWord(word.text);
+		updateWordList();
+	}
+	
+	public function removeWord():void
+	{
+		ud.removeWord(word.text);
+		updateWordList();
+	}
+	
+	]]>
+</mx:Script>		
+	<mx:HBox>
+		<mx:TextInput id="filename" text="mywords.ud"/>
+		<mx:Button id="load" label="Load/New dictionary" click="loadDict()" />
+		<mx:Button id="save" label="Save dictionary" click="saveDict()" />
+		<mx:Label id="result1" text="Result:"/> 
+	</mx:HBox>	
+	<mx:HBox>
+		<mx:TextInput id="word" text="myword"/>
+		<mx:Button id="add" label="Add Word" click="addWord()" />
+		<mx:Button id="remove" label="Remove word" click="removeWord()" />
+		<mx:Label id="result2" text="Result:"/> 
+	</mx:HBox>
+	<mx:TextArea id="wordList" height="100" width="100"/>
+	
+	<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+	<mx:Button id="check" label="Check Word" click="checkWord()"  />
+	<mx:Label id ="result" text="Result:"/>
+</mx:WindowedApplication>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CheckWord/src/CheckWord.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CheckWord/src/CheckWord.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CheckWord/src/CheckWord.mxml
new file mode 100644
index 0000000..3db2705
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CheckWord/src/CheckWord.mxml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following CheckWord MXML demonstrates how a word is checked by using Squiggly API.
+* Note that the results from this example may differ based on dictionary file.
+* 
+* The following steps are taken:
+* <ol>
+*  <li>A <code>SpellingDictionary</code> object is created </li>
+*  <li>A <code>SpellChecker</code> object is created </li>
+*  <li>In the mx:application tag, add a function call to <code>init</code> for <code>applicationComplete</code> </li>
+*  <li>Create <code>init</code> function body: in the body, add an event listener for <code>SpellingDictionary</code> object. 
+* 		Then create a <code>URLRequest</code> object to specify the url of dictionary file. Then call the <code>SpellingDictionary</code> 
+*  		object <code>load</code> method to load the dictionary from disk or remote URL.
+*  </li>
+*  <li> Finish the <code>handleLoadComplete</code> function to attach the <code>SpellingDictionary</code> object to a <code>SpellChecker</code> object</li>
+*  <li> Add a function to call the <code>CheckWord</code> method of <code>SpellChecker</code> object to verify the correctness of a word. </li>
+*  <li>Add related MXML component tag and related property. </li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingEngine.swc) in your libs folder. Please see the reference "How to generate Squiggly dictionary".
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" applicationComplete="init()">
+<mx:Script>
+	<![CDATA[
+		import com.adobe.linguistics.spelling.*;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+				_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+				_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkWord():void {
+			if( sp.checkWord( inputWord.text ) )
+				result.text = "Result:correct";
+			else
+				result.text = "Result:wrong";
+		}
+		
+	]]>
+</mx:Script>
+	<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+	<mx:Label id ="result" text="Result:"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ConfigExample/src/ConfigExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ConfigExample/src/ConfigExample.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ConfigExample/src/ConfigExample.mxml
new file mode 100644
index 0000000..f5c1b50
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ConfigExample/src/ConfigExample.mxml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following ConfigExample MXML demonstrates the use of ResourceTable.setResource method and SpellingConfiguration class.
+* Note that the results from this example may differ based on dictionary file.
+* 
+* The following steps are taken:
+* <ol>
+*  <li>Create a <code>ResourceTable</code> object.</li>
+*  <li>Map different locales with their resources using <code>ResourceTable.setResource</code> method </li>
+*  <li>Set <code>SpellingConfiguration.resourceTable</code> equal to the resource table object created above.</li>
+*  <li>Create some text areas and call<code> SpellUI.enableSpelling</code> method for spell check.</li>
+*  <li>Spell check is now done using resource set by resource table and AdobeSpellingConfig.xml is ignored.</li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingFramework.swc and AdobeSpellingUI.swc) in your libs folder. Please see the reference "How to generate Squiggly dictionary".
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" viewSourceURL="srcview/index.html" applicationComplete="init()">		
+	<mx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;
+			import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
+			import com.adobe.linguistics.spelling.framework.ResourceTable;
+			
+			
+			public function init():void
+			{
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});
+				resourceTable.setResource("es_ES", {rule:"data/es_ES.aff", dict:"data/es_ES.dic"});
+				SpellingConfiguration.resourceTable = resourceTable;
+			}
+			public function spellEnglish():void
+			{
+				SpellUI.enableSpelling(ta_en,"en_US");
+			}
+			public function spellSpanish():void
+			{
+				SpellUI.enableSpelling(ta_es,"es_ES");
+			}
+			
+		]]>
+	</mx:Script>
+	
+	<mx:Label text="ConfigExample.mxml Spell checks using SpellingConfiguration class. Does not need AdobeSpellingConfig.xml" fontSize="20"/>
+	
+	
+		
+		<mx:TextArea id="ta_en" width="50%" height="20%"
+						 text="I know Enlish. Use the context menu to see the suggestions of the missbelled word. " />
+		<mx:Button label="Spell English" id="b1" click="spellEnglish()"/>
+		
+		<mx:TextArea id="ta_es" width="50%" height="20%"
+						 text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita. " />
+		<mx:Button label="Spell Spanish" id="b2" click="spellSpanish()"/>
+
+</mx:Application>
+
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
new file mode 100644
index 0000000..9881a48
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/en_US/SquigglyContextMenu.properties
@@ -0,0 +1,19 @@
+# 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.
+
+# locale/en_US/SquigglyContextMenu.properties
+add=Add to dictionary
+enable=Enable spelling
+disable=Disable spelling

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
new file mode 100644
index 0000000..cbe3de2
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/locale/es_ES/SquigglyContextMenu.properties
@@ -0,0 +1,19 @@
+# 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.
+
+# locale/es_ES/SquigglyContextMenu.properties
+add=Añadir al diccionario
+enable=Revisar ortografía
+disable=Ignorar ortografía

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
new file mode 100644
index 0000000..44d6080
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following ContextMenuWithResource MXML demonstrates how to localize your spelling context menu with Flex resource when using Squiggly UI components.
+*  
+* <ol>
+*  <li> Call Squiggly <code>SpellUI.enableSpelling</code> method to enable spell checking when application is initialized.</li>
+*  <li> Once the locale ComboBox is changed, change localeChain and call updateContextMenuForLocaleChange() function. For more info on localization with resource, see http://livedocs.adobe.com/flex/3/html/help.html?content=l10n_1.html </li>
+*  <li> In updateContextMenuForLocaleChange(), create an associative array object with proper keys and values by getting resource from SquigglyContextMenu resource. </li>
+*  <li> Call Squiggly <code>SpellUI.setSpellingMenuEntries</code> method to customize the menu. </li>
+* </ol>
+*
+* Note: to make this example work properly, please make sure you have the proper dictionary files and AdobeSpellingConfig.xml file in the specified folder 
+* and put the Squiggly libraries (both AdobeSpellingEngine.swc and AdobeSpellingUI.swc) in you libs folder.
+*
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="init();">
+	<mx:Script>
+		<![CDATA[
+
+			import com.adobe.linguistics.spelling.SpellUI;
+			
+			[Bindable]
+			private var uiLocales:Array = ["en_US", "es_ES" ];
+			
+			private function uiLocaleChange():void
+			{
+				resourceManager.localeChain = [ localeComboBox.selectedItem ];
+				updateContextMenuForLocaleChange();
+			}
+				
+			private function updateContextMenuForLocaleChange():void
+			{
+				var contextMenu:Object = 
+					{add:resourceManager.getString('SquigglyContextMenu', 'add'),
+					 enable:resourceManager.getString('SquigglyContextMenu', 'enable'),
+					 disable:resourceManager.getString('SquigglyContextMenu', 'disable')};
+				SpellUI.setSpellingMenuEntries(contextMenu);
+			}
+			
+			private function init():void
+			{
+				SpellUI.enableSpelling(ta, "en_US");
+			}
+		]]>
+    </mx:Script>
+    
+    <mx:Metadata>
+    	[ResourceBundle("SquigglyContextMenu")]
+    </mx:Metadata>
+	<mx:Label text="Example for contextMenu customization with resource" fontSize="30"/>
+	<mx:HBox>
+		<mx:Text text="Locale for Squiggly contextMenu" color="blue"/>	
+		<mx:ComboBox id="localeComboBox" dataProvider="{uiLocales}" change="uiLocaleChange()"/>
+	</mx:HBox>
+	<mx:TextArea id="ta" width="50%" height="50%" fontSize="30" y="50" text="Sé esbañol. Utilice el menú contextual para ver las sugerencias de la palabra mal eskrita."/>
+</mx:Application>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
new file mode 100644
index 0000000..41db081
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following CustomContextMenu MXML demonstrates how to customize your spelling context menu when using Squiggly UI components.
+* 
+* 
+* <ol>
+*  <li>
+*  Create an associative array object with proper keys and values.
+*  </li>
+*  <li>
+*  Call Squiggly <code>SpellUI.setSpellingMenuEntries</code> method to customize the menu. We recommend using this API with resource bundle rather than using hard coded string.
+*  </li>
+*  <li>
+*  Call Squiggly <code>SpellUI.enableSpelling</code> method to enable spell checking.
+*  </li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary files and AdobeSpellingConfig.xml file in the specified folder 
+* and put the Squiggly libraries (both AdobeSpellingEngine.swc and AdobeSpellingUI.swc) in you libs folder.
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="init();">
+	<mx:Script>
+		<![CDATA[
+
+			import com.adobe.linguistics.spelling.SpellUI;
+				
+			public function init():void
+			{
+				// This is just for example code purpose, we recommend using this with resource bundle rather than using hard coded string.
+				var spanishEntries:Object = {enable:"Revisar ortografía", disable:"Ignorar ortografía", add:"Añadir al diccionario"};
+				var result:Boolean = SpellUI.setSpellingMenuEntries(spanishEntries);
+				if (result == false) trace("Error customizing contextMenu, default menu will be used");
+				
+				SpellUI.enableSpelling(ta, "en_US");
+			}	
+		]]>
+    </mx:Script>
+    
+	<mx:Label text="Example for Spanish contextMenu" fontSize="30"/>
+	<mx:TextArea id="ta" width="50%" height="50%" fontSize="30" y="50"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
new file mode 100644
index 0000000..912e502
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/GetSuggestion/src/GetSuggestion.mxml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following GetSuggestion MXML demonstrates how to get the suggestion list for a mispelled word by using Squiggly API.
+* Note that the results from this example may differ based on dictionary file.
+* 
+* The following steps are taken:
+* <ol>
+*  <li>A <code>SpellingDictionary</code> object is created </li>
+*  <li>A <code>SpellChecker</code> object is created </li>
+*  <li>In the mx:application tag, add a functon call to <code>init</code> for <code>applicationComplete</code> </li>
+*  <li>Create <code>init</code> function body: in the body, add a event listener for <code>SpellingDictionary</code> object. 
+* Then create a <code>URLRequest</code> object to specify the url of dictionary file. Then call the <code>SpellingDictionary</code> 
+*  object <code>load</load> method to load the dictionary from disk or remote URL.</li>
+*  <li> Finish the <code>handleLoadComplete</code> function to attach the <code>SpellingDictionary</code> object to a <code>SpellChecker</code> object</li>
+*  <li> Add a function to call the <code>CheckWord</code> method of <code>SpellChecker</code> object to verify the correctness of a word. </li>
+*  </li>
+*  <li> For the mispelled word from last step, call the <code>getSuggestions</code> method of <code>SpellChecker</code> object to query the suggestion list
+*  </li>
+*  <li>Add related MXML component tag and related property.
+* </li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingEngine.swc) in you libs folder. Please see the reference "How to generate Squiggly dictionary".
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" applicationComplete="init()" horizontalAlign="left">
+<mx:Script>
+	<![CDATA[
+		import com.adobe.linguistics.spelling.*;
+		
+		private var _newdict:HunspellDictionary = new HunspellDictionary();
+		private var sp:SpellChecker;
+		private function init():void {
+				_newdict.addEventListener(Event.COMPLETE, handleLoadComplete);
+				_newdict.load("dictionaries/en_US/en_US.aff", "dictionaries/en_US/en_US.dic");
+		}
+		private function handleLoadComplete(evt:Event):void
+		{
+			sp = new SpellChecker(_newdict);
+		}
+
+		private function checkWord():void {
+			suggestions.text= "";
+			if( sp.checkWord( inputWord.text ) ) {
+				result.text = "Result:correct";
+			}
+			else {
+				result.text = "Result:wrong";
+				var sugeestionArr:Array= sp.getSuggestions(inputWord.text);
+				if (sugeestionArr != null) {
+					for ( var i:int=0;i< sugeestionArr.length; i++ ) {
+						suggestions.text= suggestions.text + sugeestionArr[i] + "\n";
+					}
+				}
+			}
+		}
+		
+	]]>
+</mx:Script>
+	<mx:HBox>
+		<mx:TextInput id="inputWord" text ="test" keyUp="checkWord()"/>
+		<mx:Button id="check" label="Check Word" click="checkWord()"  />
+		<mx:Label id ="result" text="Result:"/>	
+	</mx:HBox>
+	<mx:TextArea id="suggestions" height="300" width="100"/>
+</mx:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
new file mode 100644
index 0000000..c51e4ac
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceEsg/src/SpellingServiceEsg.mxml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following SpellingServiceEsg MXML demonstrates the use of SpellingService class.
+* Note that the results from this example may differ based on dictionary file.
+* 
+* The following steps are taken:
+* <ol>
+*  <li>A <code>ResourceTable</code> object is created and locales are mapped to file URLs.</li>
+*  <li><code>SpellingService</code> object is created and initialized</li>
+*  <li><code>SpellingServicecheckWord</code> method is used to check word and output is displayed</li>
+*  <li>A <code>UserDictionary</code> object is created and a word is added to it.</li>
+*  <li>A word is added to the user dictionary which in turn is added to SpellingService Object using <code>SpellingService.addUserDictionary</code> method.</li>
+*  <li> <code>SpellingService.checkWord</code> API is again called.</li>
+*  <li>The userDictionary is removed using <code>SpellingService.removeUserDictionary</code> method.</li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary file in the specified folder 
+* and put the Squiggly library(AdobeSpellingEngine.swc) in your libs folder. Please see the reference "How to generate Squiggly dictionary".
+-->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+			   xmlns:s="library://ns.adobe.com/flex/spark" 
+			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="init();">
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.framework.*;
+			import com.adobe.linguistics.spelling.*;
+			
+			private var spellingService:SpellingService = null;
+			
+			private function init():void {
+				result.text += "AdobeSpellingServiceFramework tests\n===================\n";
+				result.text += "Setting SpellingConfiguration and initializing SpellingService ...\n";
+				
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});			
+				SpellingConfiguration.resourceTable = resourceTable;
+				
+				spellingService = new SpellingService("en_US");
+				spellingService.addEventListener(Event.COMPLETE, spellingServiceReady);
+				spellingService.init();
+			}
+			
+			private function spellingServiceReady(e:Event):void {
+				result.text += "SpellingService ready for use\n";
+				
+				result.text += "Checking \"hello\" ... " + spellingService.checkWord("hello") + "\n";
+				result.text += "Checking \"heello\" ... " + spellingService.checkWord("heello") + "\n";
+				result.text += "Getting suggestions for \"heello\" ... " + spellingService.getSuggestions("heello") + "\n";
+				
+				
+				var ud:UserDictionary = new UserDictionary();
+				result.text += "Adding \"heello\" to UserDictionary ..." + ud.addWord("heello") + "\n";
+				result.text += "Adding UserDicitonary to SpellingService ..." + spellingService.addUserDictionary(ud) +"\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Removing \"heello\" from UserDictionary ..." + ud.removeWord("heello") + "\n"
+				result.text += "Checking \"heello\" again, expect false ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Number of UserDictionary, expect 1 ..." + spellingService.userDictionaries.length + "\n";
+				
+				var ud2:UserDictionary = new UserDictionary();				
+				result.text += "Adding UserDicitonary 2 to SpellingService ..." + spellingService.addUserDictionary(ud2) +"\n";
+				result.text += "Adding \"heello\" to UserDictionary 2 ..." + ud2.addWord("heello") + "\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 2 ..." + spellingService.userDictionaries.length + "\n";
+				
+				spellingService.removeUserDictionary(ud);
+				spellingService.removeUserDictionary(ud2);
+				result.text += "Checking \"heello\" again after removing all UserDictionaries, expect false ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 0 ..." + spellingService.userDictionaries.length + "\n";
+				
+			}
+			
+		]]>
+	</fx:Script>
+	<mx:Text id="result"/>
+</s:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceExample/src/AdobeSpellingFrameworkExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceExample/src/AdobeSpellingFrameworkExample.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceExample/src/AdobeSpellingFrameworkExample.mxml
new file mode 100644
index 0000000..0fc24f3
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SpellingServiceExample/src/AdobeSpellingFrameworkExample.mxml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+			   xmlns:s="library://ns.adobe.com/flex/spark" 
+			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="init();">
+	<fx:Declarations>
+		<!-- Place non-visual elements (e.g., services, value objects) here -->
+	</fx:Declarations>
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.framework.*;
+			import com.adobe.linguistics.spelling.*;
+			
+			private var spellingService:SpellingService = null;
+			
+			private function init():void {
+				result.text += "AdobeSpellingServiceFramework tests\n===================\n";
+				result.text += "Setting SpellingConfiguration and initializing SpellingService ...\n";
+				
+				var resourceTable:ResourceTable = new ResourceTable();
+				resourceTable.setResource("en_US", {rule:"data/en_US.aff", dict:"data/en_US.dic"});			
+				SpellingConfiguration.resourceTable = resourceTable;
+				
+				spellingService = new SpellingService("en_US");
+				spellingService.addEventListener(Event.COMPLETE, spellingServiceReady);
+				spellingService.init();
+			}
+			
+			private function spellingServiceReady(e:Event):void {
+				result.text += "SpellingService ready for use\n";
+				
+				result.text += "Checking \"hello\" ... " + spellingService.checkWord("hello") + "\n";
+				result.text += "Checking \"heello\" ... " + spellingService.checkWord("heello") + "\n";
+				result.text += "Getting suggestions for \"heello\" ... " + spellingService.getSuggestions("heello") + "\n";
+				
+				
+				var ud:UserDictionary = new UserDictionary();
+				result.text += "Adding \"heello\" to UserDictionary ..." + ud.addWord("heello") + "\n";
+				result.text += "Adding UserDicitonary to SpellingService ..." + spellingService.addUserDictionary(ud) +"\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Removing \"heello\" from UserDictionary ..." + ud.removeWord("heello") + "\n"
+				result.text += "Checking \"heello\" again, expect false ..." + spellingService.checkWord("heello") + "\n";
+				
+				result.text += "Number of UserDictionary, expect 1 ..." + spellingService.userDictionaries.length + "\n";
+				
+				var ud2:UserDictionary = new UserDictionary();				
+				result.text += "Adding UserDicitonary 2 to SpellingService ..." + spellingService.addUserDictionary(ud2) +"\n";
+				result.text += "Adding \"heello\" to UserDictionary 2 ..." + ud2.addWord("heello") + "\n";
+				result.text += "Checking \"heello\" again, expect true ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 2 ..." + spellingService.userDictionaries.length + "\n";
+				
+				spellingService.removeUserDictionary(ud);
+				spellingService.removeUserDictionary(ud2);
+				result.text += "Checking \"heello\" again after removing all UserDictionaries, expect false ..." + spellingService.checkWord("heello") + "\n";
+				result.text += "Number of UserDictionary, expect 0 ..." + spellingService.userDictionaries.length + "\n";
+
+			}
+
+		]]>
+	</fx:Script>
+	<mx:Text id="result"/>
+</s:Application>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
new file mode 100644
index 0000000..0c4fcef
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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.
+
+-->
+<!--- 
+* @exampleText The following SquigglyUIExample MXML demonstrates how to use Squiggly UI API to easily integrate Squiggly with your own UI component.
+* 
+* Note that the results from this example may differ based on dictionary file.
+* 
+* Only one line code is needed:
+* <ol>
+*  <li>
+*  Call Squiggly <code>SpellUI.enableSpelling</code> method to attach the <code>TextArea</code> component and the dictionary file.
+*  </li>
+* </ol>
+* 
+* Note: to make this example work properly, please make sure you have the proper dictionary files and AdobeSpellingConfig.xml file in the specified folder 
+* and put the Squiggly libraries (both AdobeSpellingEngine.swc and AdobeSpellingUI.swc) in your libs folder.
+-->
+<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">		
+<mx:Script>
+	<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;	
+			
+			private function enableFeature():void {
+				SpellUI.enableSpelling(textArea, "en_US");
+			}
+			private function disableFeature() :void {
+				SpellUI.disableSpelling(textArea);
+			
+			}
+	]]>
+</mx:Script>
+		
+	<mx:TextArea id="textArea" width="20%" height="20%" fontSize="30" text="Spell cheecking in TextArea "/>
+	<mx:Button id="tt1" label="disable Feature" click="disableFeature()" /> 
+	<mx:Button id="tt2" label="enable Feature" click="enableFeature()" /> 
+			
+</mx:Application>
+

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/a52655ac/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleDictload.mxml
----------------------------------------------------------------------
diff --git a/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleDictload.mxml b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleDictload.mxml
new file mode 100644
index 0000000..01bb825
--- /dev/null
+++ b/Squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/src/SquigglyUIexampleDictload.mxml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+  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.
+
+-->
+<!--<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">	-->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
+			   xmlns:s="library://ns.adobe.com/flex/spark" 
+			   xmlns:mx="library://ns.adobe.com/flex/mx" 
+			   xmlns:popup="popup.*" 
+			   minWidth="955" minHeight="600" >
+			<!--   creationComplete="startRotation()"  viewSourceURL="srcview/index.html"--> 
+	<fx:Script>
+		<![CDATA[
+			import com.adobe.linguistics.spelling.SpellUI;	
+			/*//------------------------
+			//thread variable
+			private var thread:PseudoThread;
+			//this is a thread function added
+			private function launchThread():void
+			{
+			thread = new PseudoThread(systemManager, enableFeature);
+			thread.addEventListener("threadComplete", threadCompleteHandler);
+			}
+			//a do nothing fucntion
+			private function threadCompleteHandler(event:Event):void
+			{
+			}
+			//--------------------------*/
+			private function enableFeature():void {
+				/*	var str1:String="C:/p4_garuda1890_ugoyal-xp/esg/users/ravi/squiggly/main/ASDocExamples/com/adobe/linguistics/spelling/Examples/Flex/SquigglyUIExample/";
+				var str2:String="AdobeSpellingConfig.xml";
+				//result.text=str1+ta.text;
+				SpellUI.spellingConfigURL =str1+str2;*/
+				SpellUI.enableSpelling(textArea, "pt_PT");
+			}
+			private function disableFeature() :void {
+				SpellUI.disableSpelling(textArea);
+				
+			}
+			
+			
+			//--------------------------------
+		/*	private function startRotation():void //add this above   	
+			{
+			addEventListener("enterFrame", enterFrameHandler);
+			}
+			
+			private function enterFrameHandler(event:Event):void
+			{
+			//trace("enterFrame");
+			rbutton.rotation += 14;	
+			}
+			//---------------------------*/
+		]]>
+	</fx:Script>
+	<s:layout>
+		<s:VerticalLayout/>
+	</s:layout>
+	
+	<mx:TextArea id="textArea" width="20%" height="20%" fontSize="30" text="Spell cheecking in TextArea "/>
+	<mx:Button id="tt1" label="disable Feature" click="disableFeature()" /> 
+	<mx:Button id="tt2" label="enable Feature" click="enableFeature()" /> 
+<!--	<mx:Button id="rbutton" label="Rotating Button"/> -->
+</s:Application>
\ No newline at end of file