Text Layout Framework Donation From Adobe

git-svn-id: https://svn.apache.org/repos/asf/incubator/flex/tlf/branches/1.0@1374090 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/DISCLAIMER b/DISCLAIMER
new file mode 100644
index 0000000..46661d6
--- /dev/null
+++ b/DISCLAIMER
@@ -0,0 +1,8 @@
+Apache Flex is an effort undergoing incubation at The Apache 
+Software Foundation (ASF), sponsored by the Apache Incubator. 
+Incubation is required of all newly accepted projects until a further 
+review indicates that the infrastructure, communications, and decision 
+making process have stabilized in a manner consistent with other 
+successful ASF projects. While incubation status is not necessarily a 
+reflection of the completeness or stability of the code, it does indicate 
+that the project has yet to be fully endorsed by the ASF.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1f7e9d8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,717 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
+
+------------------------------------------------------------------------------------------
+
+For the easing algorithms used in frameworks/src/mx/effect/easing:
+
+TERMS OF USE - EASING EQUATIONS
+
+Open source under the BSD License. 
+
+Easing Equations © 2001-2003, Robert Penner
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are 
+permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of 
+conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice, this list of 
+conditions and the following disclaimer in the documentation and/or other materials 
+provided with the distribution.
+Neither the name of the author nor the names of contributors may be used to endorse or 
+promote products derived from this software without specific prior written permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+See frameworks/project/framework/src/mx/effect/easing/easing_readme.txt for more details 
+on what was used in this product.
+
+------------------------------------------------------------------------------------------
+
+For all directories except for the asc compiler in modules/asc, and modules/thirdparty 
+directories:
+
+Adobe Flex
+Copyright date 2003 - 2012 Adobe Systems Incorporated. All Rights Reserved.
+
+                          MOZILLA PUBLIC LICENSE
+                                Version 1.1
+
+                              ---------------
+
+1. Definitions.
+
+     1.0.1. "Commercial Use" means distribution or otherwise making the
+     Covered Code available to a third party.
+
+     1.1. "Contributor" means each entity that creates or contributes to
+     the creation of Modifications.
+
+     1.2. "Contributor Version" means the combination of the Original
+     Code, prior Modifications used by a Contributor, and the Modifications
+     made by that particular Contributor.
+
+     1.3. "Covered Code" means the Original Code or Modifications or the
+     combination of the Original Code and Modifications, in each case
+     including portions thereof.
+
+     1.4. "Electronic Distribution Mechanism" means a mechanism generally
+     accepted in the software development community for the electronic
+     transfer of data.
+
+     1.5. "Executable" means Covered Code in any form other than Source
+     Code.
+
+     1.6. "Initial Developer" means the individual or entity identified
+     as the Initial Developer in the Source Code notice required by Exhibit
+     A.
+
+     1.7. "Larger Work" means a work which combines Covered Code or
+     portions thereof with code not governed by the terms of this License.
+
+     1.8. "License" means this document.
+
+     1.8.1. "Licensable" means having the right to grant, to the maximum
+     extent possible, whether at the time of the initial grant or
+     subsequently acquired, any and all of the rights conveyed herein.
+
+     1.9. "Modifications" means any addition to or deletion from the
+     substance or structure of either the Original Code or any previous
+     Modifications. When Covered Code is released as a series of files, a
+     Modification is:
+          A. Any addition to or deletion from the contents of a file
+          containing Original Code or previous Modifications.
+
+          B. Any new file that contains any part of the Original Code or
+          previous Modifications.
+
+     1.10. "Original Code" means Source Code of computer software code
+     which is described in the Source Code notice required by Exhibit A as
+     Original Code, and which, at the time of its release under this
+     License is not already Covered Code governed by this License.
+
+     1.10.1. "Patent Claims" means any patent claim(s), now owned or
+     hereafter acquired, including without limitation,  method, process,
+     and apparatus claims, in any patent Licensable by grantor.
+
+     1.11. "Source Code" means the preferred form of the Covered Code for
+     making modifications to it, including all modules it contains, plus
+     any associated interface definition files, scripts used to control
+     compilation and installation of an Executable, or source code
+     differential comparisons against either the Original Code or another
+     well known, available Covered Code of the Contributor's choice. The
+     Source Code can be in a compressed or archival form, provided the
+     appropriate decompression or de-archiving software is widely available
+     for no charge.
+
+     1.12. "You" (or "Your")  means an individual or a legal entity
+     exercising rights under, and complying with all of the terms of, this
+     License or a future version of this License issued under Section 6.1.
+     For legal entities, "You" includes any entity which controls, is
+     controlled by, or is under common control with You. For purposes of
+     this definition, "control" means (a) the power, direct or indirect,
+     to cause the direction or management of such entity, whether by
+     contract or otherwise, or (b) ownership of more than fifty percent
+     (50%) of the outstanding shares or beneficial ownership of such
+     entity.
+
+2. Source Code License.
+
+     2.1. The Initial Developer Grant.
+     The Initial Developer hereby grants You a world-wide, royalty-free,
+     non-exclusive license, subject to third party intellectual property
+     claims:
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Initial Developer to use, reproduce,
+          modify, display, perform, sublicense and distribute the Original
+          Code (or portions thereof) with or without Modifications, and/or
+          as part of a Larger Work; and
+
+          (b) under Patents Claims infringed by the making, using or
+          selling of Original Code, to make, have made, use, practice,
+          sell, and offer for sale, and/or otherwise dispose of the
+          Original Code (or portions thereof).
+
+          (c) the licenses granted in this Section 2.1(a) and (b) are
+          effective on the date Initial Developer first distributes
+          Original Code under the terms of this License.
+
+          (d) Notwithstanding Section 2.1(b) above, no patent license is
+          granted: 1) for code that You delete from the Original Code; 2)
+          separate from the Original Code;  or 3) for infringements caused
+          by: i) the modification of the Original Code or ii) the
+          combination of the Original Code with other software or devices.
+
+     2.2. Contributor Grant.
+     Subject to third party intellectual property claims, each Contributor
+     hereby grants You a world-wide, royalty-free, non-exclusive license
+
+          (a)  under intellectual property rights (other than patent or
+          trademark) Licensable by Contributor, to use, reproduce, modify,
+          display, perform, sublicense and distribute the Modifications
+          created by such Contributor (or portions thereof) either on an
+          unmodified basis, with other Modifications, as Covered Code
+          and/or as part of a Larger Work; and
+
+          (b) under Patent Claims infringed by the making, using, or
+          selling of  Modifications made by that Contributor either alone
+          and/or in combination with its Contributor Version (or portions
+          of such combination), to make, use, sell, offer for sale, have
+          made, and/or otherwise dispose of: 1) Modifications made by that
+          Contributor (or portions thereof); and 2) the combination of
+          Modifications made by that Contributor with its Contributor
+          Version (or portions of such combination).
+
+          (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+          effective on the date Contributor first makes Commercial Use of
+          the Covered Code.
+
+          (d)    Notwithstanding Section 2.2(b) above, no patent license is
+          granted: 1) for any code that Contributor has deleted from the
+          Contributor Version; 2)  separate from the Contributor Version;
+          3)  for infringements caused by: i) third party modifications of
+          Contributor Version or ii)  the combination of Modifications made
+          by that Contributor with other software  (except as part of the
+          Contributor Version) or other devices; or 4) under Patent Claims
+          infringed by Covered Code in the absence of Modifications made by
+          that Contributor.
+
+3. Distribution Obligations.
+
+     3.1. Application of License.
+     The Modifications which You create or to which You contribute are
+     governed by the terms of this License, including without limitation
+     Section 2.2. The Source Code version of Covered Code may be
+     distributed only under the terms of this License or a future version
+     of this License released under Section 6.1, and You must include a
+     copy of this License with every copy of the Source Code You
+     distribute. You may not offer or impose any terms on any Source Code
+     version that alters or restricts the applicable version of this
+     License or the recipients' rights hereunder. However, You may include
+     an additional document offering the additional rights described in
+     Section 3.5.
+
+     3.2. Availability of Source Code.
+     Any Modification which You create or to which You contribute must be
+     made available in Source Code form under the terms of this License
+     either on the same media as an Executable version or via an accepted
+     Electronic Distribution Mechanism to anyone to whom you made an
+     Executable version available; and if made available via Electronic
+     Distribution Mechanism, must remain available for at least twelve (12)
+     months after the date it initially became available, or at least six
+     (6) months after a subsequent version of that particular Modification
+     has been made available to such recipients. You are responsible for
+     ensuring that the Source Code version remains available even if the
+     Electronic Distribution Mechanism is maintained by a third party.
+
+     3.3. Description of Modifications.
+     You must cause all Covered Code to which You contribute to contain a
+     file documenting the changes You made to create that Covered Code and
+     the date of any change. You must include a prominent statement that
+     the Modification is derived, directly or indirectly, from Original
+     Code provided by the Initial Developer and including the name of the
+     Initial Developer in (a) the Source Code, and (b) in any notice in an
+     Executable version or related documentation in which You describe the
+     origin or ownership of the Covered Code.
+
+     3.4. Intellectual Property Matters
+          (a) Third Party Claims.
+          If Contributor has knowledge that a license under a third party's
+          intellectual property rights is required to exercise the rights
+          granted by such Contributor under Sections 2.1 or 2.2,
+          Contributor must include a text file with the Source Code
+          distribution titled "LEGAL" which describes the claim and the
+          party making the claim in sufficient detail that a recipient will
+          know whom to contact. If Contributor obtains such knowledge after
+          the Modification is made available as described in Section 3.2,
+          Contributor shall promptly modify the LEGAL file in all copies
+          Contributor makes available thereafter and shall take other steps
+          (such as notifying appropriate mailing lists or newsgroups)
+          reasonably calculated to inform those who received the Covered
+          Code that new knowledge has been obtained.
+
+          (b) Contributor APIs.
+          If Contributor's Modifications include an application programming
+          interface and Contributor has knowledge of patent licenses which
+          are reasonably necessary to implement that API, Contributor must
+          also include this information in the LEGAL file.
+
+               (c)    Representations.
+          Contributor represents that, except as disclosed pursuant to
+          Section 3.4(a) above, Contributor believes that Contributor's
+          Modifications are Contributor's original creation(s) and/or
+          Contributor has sufficient rights to grant the rights conveyed by
+          this License.
+
+     3.5. Required Notices.
+     You must duplicate the notice in Exhibit A in each file of the Source
+     Code.  If it is not possible to put such notice in a particular Source
+     Code file due to its structure, then You must include such notice in a
+     location (such as a relevant directory) where a user would be likely
+     to look for such a notice.  If You created one or more Modification(s)
+     You may add your name as a Contributor to the notice described in
+     Exhibit A.  You must also duplicate this License in any documentation
+     for the Source Code where You describe recipients' rights or ownership
+     rights relating to Covered Code.  You may choose to offer, and to
+     charge a fee for, warranty, support, indemnity or liability
+     obligations to one or more recipients of Covered Code. However, You
+     may do so only on Your own behalf, and not on behalf of the Initial
+     Developer or any Contributor. You must make it absolutely clear than
+     any such warranty, support, indemnity or liability obligation is
+     offered by You alone, and You hereby agree to indemnify the Initial
+     Developer and every Contributor for any liability incurred by the
+     Initial Developer or such Contributor as a result of warranty,
+     support, indemnity or liability terms You offer.
+
+     3.6. Distribution of Executable Versions.
+     You may distribute Covered Code in Executable form only if the
+     requirements of Section 3.1-3.5 have been met for that Covered Code,
+     and if You include a notice stating that the Source Code version of
+     the Covered Code is available under the terms of this License,
+     including a description of how and where You have fulfilled the
+     obligations of Section 3.2. The notice must be conspicuously included
+     in any notice in an Executable version, related documentation or
+     collateral in which You describe recipients' rights relating to the
+     Covered Code. You may distribute the Executable version of Covered
+     Code or ownership rights under a license of Your choice, which may
+     contain terms different from this License, provided that You are in
+     compliance with the terms of this License and that the license for the
+     Executable version does not attempt to limit or alter the recipient's
+     rights in the Source Code version from the rights set forth in this
+     License. If You distribute the Executable version under a different
+     license You must make it absolutely clear that any terms which differ
+     from this License are offered by You alone, not by the Initial
+     Developer or any Contributor. You hereby agree to indemnify the
+     Initial Developer and every Contributor for any liability incurred by
+     the Initial Developer or such Contributor as a result of any such
+     terms You offer.
+
+     3.7. Larger Works.
+     You may create a Larger Work by combining Covered Code with other code
+     not governed by the terms of this License and distribute the Larger
+     Work as a single product. In such a case, You must make sure the
+     requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+     If it is impossible for You to comply with any of the terms of this
+     License with respect to some or all of the Covered Code due to
+     statute, judicial order, or regulation then You must: (a) comply with
+     the terms of this License to the maximum extent possible; and (b)
+     describe the limitations and the code they affect. Such description
+     must be included in the LEGAL file described in Section 3.4 and must
+     be included with all distributions of the Source Code. Except to the
+     extent prohibited by statute or regulation, such description must be
+     sufficiently detailed for a recipient of ordinary skill to be able to
+     understand it.
+
+5. Application of this License.
+
+     This License applies to code to which the Initial Developer has
+     attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+     6.1. New Versions.
+     Netscape Communications Corporation ("Netscape") may publish revised
+     and/or new versions of the License from time to time. Each version
+     will be given a distinguishing version number.
+
+     6.2. Effect of New Versions.
+     Once Covered Code has been published under a particular version of the
+     License, You may always continue to use it under the terms of that
+     version. You may also choose to use such Covered Code under the terms
+     of any subsequent version of the License published by Netscape. No one
+     other than Netscape has the right to modify the terms applicable to
+     Covered Code created under this License.
+
+     6.3. Derivative Works.
+     If You create or use a modified version of this License (which you may
+     only do in order to apply it to code which is not already Covered Code
+     governed by this License), You must (a) rename Your license so that
+     the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+     "MPL", "NPL" or any confusingly similar phrase do not appear in your
+     license (except to note that your license differs from this License)
+     and (b) otherwise make it clear that Your version of the license
+     contains terms which differ from the Mozilla Public License and
+     Netscape Public License. (Filling in the name of the Initial
+     Developer, Original Code or Contributor in the notice described in
+     Exhibit A shall not of themselves be deemed to be modifications of
+     this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+     COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+     WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+     WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+     DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+     THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+     IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+     YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+     COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+     OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+     ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+     8.1.  This License and the rights granted hereunder will terminate
+     automatically if You fail to comply with terms herein and fail to cure
+     such breach within 30 days of becoming aware of the breach. All
+     sublicenses to the Covered Code which are properly granted shall
+     survive any termination of this License. Provisions which, by their
+     nature, must remain in effect beyond the termination of this License
+     shall survive.
+
+     8.2.  If You initiate litigation by asserting a patent infringement
+     claim (excluding declatory judgment actions) against Initial Developer
+     or a Contributor (the Initial Developer or Contributor against whom
+     You file such action is referred to as "Participant")  alleging that:
+
+     (a)  such Participant's Contributor Version directly or indirectly
+     infringes any patent, then any and all rights granted by such
+     Participant to You under Sections 2.1 and/or 2.2 of this License
+     shall, upon 60 days notice from Participant terminate prospectively,
+     unless if within 60 days after receipt of notice You either: (i)
+     agree in writing to pay Participant a mutually agreeable reasonable
+     royalty for Your past and future use of Modifications made by such
+     Participant, or (ii) withdraw Your litigation claim with respect to
+     the Contributor Version against such Participant.  If within 60 days
+     of notice, a reasonable royalty and payment arrangement are not
+     mutually agreed upon in writing by the parties or the litigation claim
+     is not withdrawn, the rights granted by Participant to You under
+     Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+     the 60 day notice period specified above.
+
+     (b)  any software, hardware, or device, other than such Participant's
+     Contributor Version, directly or indirectly infringes any patent, then
+     any rights granted to You by such Participant under Sections 2.1(b)
+     and 2.2(b) are revoked effective as of the date You first made, used,
+     sold, distributed, or had made, Modifications made by that
+     Participant.
+
+     8.3.  If You assert a patent infringement claim against Participant
+     alleging that such Participant's Contributor Version directly or
+     indirectly infringes any patent where such claim is resolved (such as
+     by license or settlement) prior to the initiation of patent
+     infringement litigation, then the reasonable value of the licenses
+     granted by such Participant under Sections 2.1 or 2.2 shall be taken
+     into account in determining the amount or value of any payment or
+     license.
+
+     8.4.  In the event of termination under Sections 8.1 or 8.2 above,
+     all end user license agreements (excluding distributors and resellers)
+     which have been validly granted by You or any distributor hereunder
+     prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+     UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+     (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+     DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+     OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+     ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+     CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+     WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+     COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+     INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+     LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+     RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+     PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+     EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+     THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+     The Covered Code is a "commercial item," as that term is defined in
+     48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+     software" and "commercial computer software documentation," as such
+     terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+     C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+     all U.S. Government End Users acquire Covered Code with only those
+     rights set forth herein.
+
+11. MISCELLANEOUS.
+
+     This License represents the complete agreement concerning subject
+     matter hereof. If any provision of this License is held to be
+     unenforceable, such provision shall be reformed only to the extent
+     necessary to make it enforceable. This License shall be governed by
+     California law provisions (except to the extent applicable law, if
+     any, provides otherwise), excluding its conflict-of-law provisions.
+     With respect to disputes in which at least one party is a citizen of,
+     or an entity chartered or registered to do business in the United
+     States of America, any litigation relating to this License shall be
+     subject to the jurisdiction of the Federal Courts of the Northern
+     District of California, with venue lying in Santa Clara County,
+     California, with the losing party responsible for costs, including
+     without limitation, court costs and reasonable attorneys' fees and
+     expenses. The application of the United Nations Convention on
+     Contracts for the International Sale of Goods is expressly excluded.
+     Any law or regulation which provides that the language of a contract
+     shall be construed against the drafter shall not apply to this
+     License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+     As between Initial Developer and the Contributors, each party is
+     responsible for claims and damages arising, directly or indirectly,
+     out of its utilization of rights under this License and You agree to
+     work with Initial Developer and Contributors to distribute such
+     responsibility on an equitable basis. Nothing herein is intended or
+     shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+     Initial Developer may designate portions of the Covered Code as
+     "Multiple-Licensed".  "Multiple-Licensed" means that the Initial
+     Developer permits you to utilize portions of the Covered Code under
+     Your choice of the NPL or the alternative licenses, if any, specified
+     by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+     ``The contents of this file are subject to the Mozilla Public License
+     Version 1.1 (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.mozilla.org/MPL/
+
+     Software distributed under the License is distributed on an "AS IS"
+     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+     License for the specific language governing rights and limitations
+     under the License.
+
+     The Original Code is ______________________________________.
+
+     The Initial Developer of the Original Code is ________________________.
+     Portions created by ______________________ are Copyright (C) ______
+     _______________________. All Rights Reserved.
+
+     Contributor(s): ______________________________________.
+
+     Alternatively, the contents of this file may be used under the terms
+     of the _____ license (the  "[___] License"), in which case the
+     provisions of [______] License are applicable instead of those
+     above.  If you wish to allow use of your version of this file only
+     under the terms of the [____] License and not to allow others to use
+     your version of this file under the MPL, indicate your decision by
+     deleting  the provisions above and replace  them with the notice and
+     other provisions required by the [___] License.  If you do not delete
+     the provisions above, a recipient may use your version of this file
+     under either the MPL or the [___] License."
+
+     [NOTE: The text of this Exhibit A may differ slightly from the text of
+     the notices in the Source Code files of the Original Code. You should
+     use the text of this Exhibit A rather than the text found in the
+     Original Code Source Code for Your Modifications.]
+
+------------------------------------------------------------------------------------------
+
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..8057945
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,9 @@
+Apache Flex Text Layout Framework
+Copyright 2012 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the Original Code, known as Adobe Text Layout Framework, is Adobe Systems Incorporated (http://www.adobe.com/).
+    Copyright 2003 - 2012 Adobe Systems Incorporated. All Rights Reserved.
+
diff --git a/build.xml b/build.xml
new file mode 100755
index 0000000..de709ee
--- /dev/null
+++ b/build.xml
@@ -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.
+-->
+
+<project name="tlf" default="main" basedir=".">
+	<property name="FLEX_HOME" value="D:\flex_sdk_4.5.0.19786"/>
+	<property name="flex.sdk.frameworks" value="${FLEX_HOME}/frameworks"/>
+	<property name="flex.locale" value="en_US"/>
+
+	<property name="output.dir" value="bin"/>
+	<property name="output.docs" value="${FLEX_HOME}/tempDoc"/>
+	<property name="flexTasks.location" value="${FLEX_HOME}/ant/lib/flexTasks.jar"/>
+	<property name="project.uri" value="library://ns.adobe.com/flashx/textLayout"/>
+	<property name="compc.jvm.args" value="-Xmx384m" />
+	<property name="textLayout.namespace" value="flashx.textLayout"/>
+	
+	<property name="textLayout_core.dir" value="${basedir}/textLayout_core"/>
+	<property name="textLayout_layout.dir" value="${basedir}/textLayout_layout"/>
+	<property name="textLayout_conversion.dir" value="${basedir}/textLayout_conversion"/>
+	<property name="textLayout_edit.dir" value="${basedir}/textLayout_edit"/>
+	<property name="test.dir" value="${basedir}/test"/>
+
+        <!-- We use abbreviated token names here as, the 'release' 
+             and 'debug' tokens conflict with those specified in 
+             build.properties -->
+	<property name="dbg" value="false"/>
+	<property name="rel" value="true"/>
+
+	<condition property="digest" value="false" else="true">
+		<istrue value="${debug}"/>
+	</condition>
+
+	<taskdef resource="flexTasks.tasks" classpath="${flexTasks.location}"/>
+	<target name="main" depends="clean,textLayout_core, textLayout_conversion, textLayout_layout, textLayout_edit"/>
+
+	<target name="clean" description="Cleans all SWCs and SWFs">
+		<delete failonerror="false">
+			<fileset dir="${output.dir}">
+			</fileset>
+		</delete>
+	</target>
+
+	<target name="textLayout_core" description="Compiles textLayout_core.swc">
+   		<compc fork="true"
+			   output="${output.dir}/textLayout_core.swc"
+			   compute-digest="true"
+			   include-classes="flashx.textLayout.CoreClasses">
+			<jvmarg line="${compc.jvm.args}"/>
+			<include-namespaces uri="${project.uri}"/>
+			<namespace uri="${project.uri}" manifest="${textLayout_core.dir}/manifest.xml"/>
+			<source-path path-element="${textLayout_core.dir}/src"/>
+			<library-path/>
+			<include-file name="manifest.xml" path="${textLayout_core.dir}/manifest.xml"/>
+			<external-library-path dir="${flex.sdk.frameworks}/libs/player/10.0" includes="playerglobal.swc" 	append="false"/>
+			<static-link-runtime-shared-libraries/>
+			<define name="CONFIG::debug" value="${dbg}"/>
+			<define name="CONFIG::release" value="${rel}"/>
+		</compc>
+     </target>
+		 
+	 <target name="textLayout_conversion" description="Compiles textLayout_conversion.swc">
+   		<compc fork="true"
+			   output="${output.dir}/textLayout_conversion.swc"
+			   compute-digest="true"
+			   include-classes="flashx.textLayout.ConversionClasses">
+			<jvmarg line="${compc.jvm.args}"/>
+			
+			<source-path path-element="${textLayout_conversion.dir}/src"/>
+			<library-path/>
+			
+			<external-library-path dir="${flex.sdk.frameworks}/libs/player/10.0" includes="playerglobal.swc" 	append="false"/>
+			<external-library-path dir="${output.dir}" includes="textLayout_core.swc" 	append="true"/>
+			<static-link-runtime-shared-libraries/>
+			<define name="CONFIG::debug" value="${dbg}"/>
+			<define name="CONFIG::release" value="${rel}"/>
+		</compc>
+     </target>
+	
+	<target name="textLayout_layout" description="Compiles textLayout_layout.swc">
+   		<compc fork="true"
+			   output="${output.dir}/textLayout_layout.swc"
+			   compute-digest="true"
+			   include-classes="flashx.textLayout.LayoutClasses">
+			<jvmarg line="${compc.jvm.args}"/>
+			
+			<source-path path-element="${textLayout_layout.dir}/src"/>
+			<library-path/>
+			
+			<external-library-path dir="${flex.sdk.frameworks}/libs/player/10.0" includes="playerglobal.swc" 	append="false"/>
+			<external-library-path dir="${output.dir}" includes="textLayout_core.swc" 	append="true"/>
+			<external-library-path dir="${output.dir}" includes="textLayout_conversion.swc" 		append="true"/>
+			<static-link-runtime-shared-libraries/>
+			<define name="CONFIG::debug" value="${dbg}"/>
+			<define name="CONFIG::release" value="${rel}"/>
+		</compc>
+     </target>
+	 
+	 <target name="textLayout_edit" description="Compiles textLayout_edit.swc">
+   		<compc fork="true"
+			   output="${output.dir}/textLayout_edit.swc"
+			   compute-digest="true"
+			   include-classes="flashx.textLayout.EditClasses">
+			<jvmarg line="${compc.jvm.args}"/>
+
+			<source-path path-element="${textLayout_edit.dir}/src"/>
+			<library-path/>
+			
+			<external-library-path dir="${flex.sdk.frameworks}/libs/player/10.0" includes="playerglobal.swc" 	append="false"/>
+			<external-library-path dir="${output.dir}" includes="textLayout_core.swc" 	append="true"/>
+			<external-library-path dir="${output.dir}" includes="textLayout_conversion.swc" 		append="true"/>
+			<static-link-runtime-shared-libraries/>
+			<define name="CONFIG::debug" value="${dbg}"/>
+			<define name="CONFIG::release" value="${rel}"/>
+		</compc>
+     </target>
+
+</project>
diff --git a/config.xml b/config.xml
new file mode 100755
index 0000000..6a6c342
--- /dev/null
+++ b/config.xml
@@ -0,0 +1,34 @@
+<?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.
+-->
+<!-- Settings for compiling Vellum with Eclipse -->
+<flex-config xmlns="http://www.adobe.com/2006/flex-config">
+  <compiler>
+	<define>
+      <name>CONFIG::debug</name>
+      <value>false</value>
+    </define>
+    <define>
+      <name>CONFIG::release</name>
+      <value>true</value>
+    </define>
+  </compiler>
+  <!-- this may be redundant if its also set in the SDK.  -->
+  <!-- some versions of the flex compilers may generate errors on multiple settings -->
+  <target-player>10.0.0</target-player>
+  <static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
+</flex-config>
diff --git a/textLayout_conversion/.actionScriptProperties b/textLayout_conversion/.actionScriptProperties
new file mode 100755
index 0000000..602e000
--- /dev/null
+++ b/textLayout_conversion/.actionScriptProperties
@@ -0,0 +1,63 @@
+# 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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<actionScriptProperties mainApplicationPath="textLayout_conversion.as" projectUUID="c4b9cf5f-a4b7-497c-b3e2-c56e5572f10f" version="6">
+  <compiler additionalCompilerArguments="-locale en_US -load-config+=../../config.xml" autoRSLOrdering="true" copyDependentFiles="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+    <compilerSourcePath/>
+    <libraryPath defaultLinkType="0">
+      <libraryPathEntry kind="3" linkType="4" path="/textLayout_core/bin/textLayout_core.swc" useDefaultLinkType="true"/>
+      <libraryPathEntry kind="4" path="">
+        <excludedEntries>
+          <libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="4" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/rpc_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="rpc_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="2" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/framework_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="framework_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="1" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/textLayout.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/textLayout_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="textLayout_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="3" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/spark_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="spark_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
+        </excludedEntries>
+      </libraryPathEntry>
+    </libraryPath>
+    <sourceAttachmentPath/>
+  </compiler>
+  <applications>
+    <application path="textLayout_conversion.as"/>
+  </applications>
+  <modules/>
+  <buildCSSFiles/>
+</actionScriptProperties>
diff --git a/textLayout_conversion/.flexLibProperties b/textLayout_conversion/.flexLibProperties
new file mode 100755
index 0000000..651ebac
--- /dev/null
+++ b/textLayout_conversion/.flexLibProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<flexLibProperties includeAllClasses="false" version="3">
+  <includeClasses>
+    <classEntry path="flashx.textLayout.ConversionClasses"/>
+  </includeClasses>
+  <includeResources/>
+  <namespaceManifests/>
+</flexLibProperties>
diff --git a/textLayout_conversion/.project b/textLayout_conversion/.project
new file mode 100755
index 0000000..cdd2333
--- /dev/null
+++ b/textLayout_conversion/.project
@@ -0,0 +1,35 @@
+<?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.
+-->
+<projectDescription>
+	<name>textLayout_conversion</name>
+	<comment></comment>
+	<projects>
+		<project>textLayout_core</project>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.adobe.flexbuilder.project.flexbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
+		<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
+	</natures>
+</projectDescription>
diff --git a/textLayout_conversion/src/flashx/textLayout/ConversionClasses.as b/textLayout_conversion/src/flashx/textLayout/ConversionClasses.as
new file mode 100755
index 0000000..c45c534
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/ConversionClasses.as
@@ -0,0 +1,29 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout
+{
+	internal class ConversionClasses
+	{
+		import flashx.textLayout.conversion.ITextImporter; ITextImporter; 
+		import flashx.textLayout.conversion.ITextExporter; ITextExporter; 
+		import flashx.textLayout.conversion.TextConverter; TextConverter;
+		import flashx.textLayout.conversion.TextLayoutImporter; TextLayoutImporter;
+		// Alphabetical list of classes to be included as part of text_conversion.swc
+	}
+}
\ No newline at end of file
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
new file mode 100755
index 0000000..5cbcfa4
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutExporter.as
@@ -0,0 +1,425 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flash.utils.getQualifiedClassName;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.WhiteSpaceCollapse;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** 
+	 * @private 
+	 * Export filter for TextLayout format. 
+	 */
+	internal class BaseTextLayoutExporter implements ITextExporter
+	{	
+		private var _config:ImportExportConfiguration;
+		private var _rootTag:XML;
+		private var _ns:Namespace;
+				
+		public function BaseTextLayoutExporter(ns:Namespace, rootTag:XML, config:ImportExportConfiguration)
+		{
+			_config = config;
+			_ns = ns;
+			_rootTag = rootTag;
+		}
+
+		
+		/** Clear results from last export. */
+		protected function clear():void
+		{
+			// does nothing
+		}
+		
+		/** Export text content
+		 * @param source	the text to export
+		 * @param conversionType 	what type to return
+		 * @return Object	the exported content
+		 */
+		public function export(source:TextFlow, conversionType:String):Object
+		{
+			clear();
+			if (conversionType == ConversionType.STRING_TYPE)
+				return exportToString(source);
+			else if (conversionType == ConversionType.XML_TYPE)
+				return exportToXML(source);
+			return null;
+		}
+
+		/** Export text content of a TextFlow into XFL format.
+		 * @param source	the text to export
+		 * @return XML	the exported content
+		 */
+		protected function exportToXML(textFlow:TextFlow) : XML
+		{
+			var result:XML;
+			if (_rootTag)
+			{
+				result = new XML(_rootTag);
+				result.addNamespace(_ns);
+				result.appendChild(exportChild(textFlow));
+			}
+			else
+			{
+				result = XML(exportTextFlow(this, textFlow));
+				result.addNamespace(_ns);
+			}
+			return result;
+		}
+		
+		/** Export text content as a string
+		 * @param source	the text to export
+		 * @return String	the exported content
+		 */
+		protected function exportToString(source:TextFlow):String
+		{
+			var result:String;
+			// We do some careful type casting here so that leading and trailing spaces in the XML don't
+			// get dropped when it is converted to a string
+			var originalSettings:Object = XML.settings();
+			try
+			{
+				XML.ignoreProcessingInstructions = false;		
+				XML.ignoreWhitespace = false;
+				XML.prettyPrinting = false;
+				result = exportToXML(source).toXMLString();
+				XML.setSettings(originalSettings);
+			}
+			
+			catch(e:Error)
+			{
+				XML.setSettings(originalSettings);
+				throw(e);
+			}		
+			return result;
+		}
+
+	
+		/** Base functionality for exporting a FlowElement. 
+		 * @param exporter	Root object for the export
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportFlowElement(exporter:BaseTextLayoutExporter, flowElement:FlowElement):XMLList
+		{
+			return exporter.exportFlowElement(flowElement);
+		}
+		
+		/** Overridable worker method for exporting a FlowElement. Creates the XMLList.
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportFlowElement (flowElement:FlowElement):XMLList
+		{
+			var className:String = flash.utils.getQualifiedClassName(flowElement);
+			var elementName:String = _config.lookupName(className);
+			var output:XML = <{elementName}/>;
+			output.setNamespace(_ns);
+			return XMLList(output);
+		}
+		
+		static public function exportSpanText(destination:XML, span:SpanElement, replacementRegex:RegExp, replacementXMLCallback:Function):void
+		{
+			//get the text for this span
+			var spanText:String = span.text;
+
+			// Check to see if it has text that needs to be converted			
+			var matchLocation:Array = spanText.match(replacementRegex);
+			
+			if(matchLocation)	
+			{
+				var dummy:XML;
+				
+				// We have text that has characters to be converted. Break it up into runs of text interspersed with elements corresponding to match these characters
+				while(matchLocation != null)
+				{
+					var ix:int = matchLocation.index;
+					var tempStr:String = spanText.substr(0, ix);
+					
+					//if we have some text which does not need to be replaced, then write it now
+					if(tempStr.length > 0)
+					{
+						// output[0].appendChild(tempStr); // extraneous tags can appear around a string child added after an XML element: see bug 1852072  
+						
+						// workaround for above-mentioned bug
+						dummy = <dummy/>;
+						dummy.appendChild(tempStr); // no extraneous tags here since there is no preceding XML element sibling
+						destination.appendChild(dummy.text()[0]);
+					}
+					
+					var replacementXML:XML = replacementXMLCallback(spanText.charAt(ix));
+					CONFIG::debug{ assert(replacementXML != null, "Specified match regex, but provided null replacement XML"); }
+					destination.appendChild(replacementXML);
+					
+					//remove the text up to this point
+					spanText = spanText.slice(ix + 1, spanText.length);
+					
+					//look for another character to be replaced
+					matchLocation = spanText.match(replacementRegex);
+					
+					//if we don't have any more matches, but there is still text, write that out as the last span
+					if(!matchLocation && spanText.length > 0)
+					{
+						// output[0].appendChild(spanText); // extraneous tags can appear around a string child added after an XML element: see bug 1852072  
+						
+						// workaround for above-mentioned bug
+						dummy = <dummy/>;
+						dummy.appendChild(spanText); // no extraneous tags here since there is no preceding XML element sibling
+						destination.appendChild(dummy.text()[0]);
+					}
+				}
+			}
+			else
+			{
+				//this is the simple case where we don't have a character to replace
+				destination.appendChild(span.text);
+			}		
+		}  
+		
+		/** Base functionality for exporting a Span. Exports as a FlowElement,
+		 * and exports the text of the span.
+		 * @param exporter	Root object for the export
+		 * @param span	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportSpan(exporter:BaseTextLayoutExporter, span:SpanElement):XMLList
+		{
+			var output:XMLList = exportFlowElement(exporter, span);	
+			exportSpanText(output[0], span, exporter.spanTextReplacementRegex, exporter.getSpanTextReplacementXML);
+			return output;
+		}
+		
+		static private const brRegEx:RegExp = /\u2028/;
+		
+		/** Gets the regex that specifies characters in span text to be replaced with XML elements
+		 *  Note: Each match is a single character 
+		 */
+		protected function get spanTextReplacementRegex():RegExp
+		{
+			return brRegEx;
+		}
+
+		/** Gets the xml element used to represent a character in the export format
+		 */
+		protected function getSpanTextReplacementXML(ch:String):XML
+		{
+			CONFIG::debug {assert(ch == '\u2028', "Did not recognize character to be replaced with XML"); }
+			var breakXML:XML = <br/>;
+			breakXML.setNamespace(flowNS);
+			return breakXML;
+		}
+		
+		/** Base functionality for exporting a FlowGroupElement. Exports as a FlowElement,
+		 * and exports the children of a element.
+		 * @param exporter	Root object for the export
+		 * @param flowBlockElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportFlowGroupElement(exporter:BaseTextLayoutExporter, flowBlockElement:FlowGroupElement):XMLList
+		{
+			var output:XMLList = exportFlowElement(exporter, flowBlockElement);
+			
+			// output each child
+			for(var childIter:int = 0; childIter < flowBlockElement.numChildren; ++childIter)
+			{
+				var flowChild:FlowElement = flowBlockElement.getChildAt(childIter);
+				var childXML:XMLList = exporter.exportChild(flowChild);
+				if (childXML)
+					output.appendChild(childXML);
+			}
+			return output;
+		}
+
+		/** Base functionality for exporting a ParagraphFormattedElement. Exports as a FlowGroupElement,
+		 * and exports paragraph attributes.
+		 * @param exporter	Root object for the export
+		 * @param flowParagraph	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportParagraphFormattedElement(exporter:BaseTextLayoutExporter, flowParagraph:ParagraphFormattedElement):XMLList
+		{
+			return exporter.exportParagraphFormattedElement(flowParagraph);
+		}
+		
+		/** Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportParagraphFormattedElement(flowElement:FlowElement):XMLList
+		{
+			var rslt:XMLList = exportFlowElement(flowElement);
+			// output each child
+			for(var childIter:int = 0; childIter < ParagraphFormattedElement(flowElement).numChildren; ++childIter)
+			{
+				var flowChild:FlowElement = ParagraphFormattedElement(flowElement).getChildAt(childIter);
+				rslt.appendChild(exportChild(flowChild));
+			}
+			return rslt;
+		}
+		/** Base functionality for exporting a ContainerFormattedElement. Exports as a ParagraphFormattedElement,
+		 * and exports container attributes.
+		 * @param exporter	Root object for the export
+		 * @param container	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportContainerFormattedElement(exporter:BaseTextLayoutExporter, container:ContainerFormattedElement):XMLList
+		{
+			return exporter.exportContainerFormattedElement(container);
+		}
+		
+		/** Overridable worker method for exporting a ParagraphFormattedElement. Creates the XMLList.
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		protected function exportContainerFormattedElement(flowElement:FlowElement):XMLList
+		{
+			return exportParagraphFormattedElement(flowElement);
+		}
+
+		/** Base functionality for exporting a TextFlow. Exports as a ContainerElement,
+		 * and exports container attributes.
+		 * @param exporter	Root object for the export
+		 * @param textFlow	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTextFlow(exporter:BaseTextLayoutExporter, textFlow:TextFlow):XMLList
+		{
+			var output:XMLList = exportContainerFormattedElement(exporter, textFlow);
+			
+			// TextLayout will use PRESERVE on output
+			output.@[TextLayoutFormat.whiteSpaceCollapseProperty.name] = WhiteSpaceCollapse.PRESERVE;
+						
+			return output;
+		}
+
+
+		/** Exports the object. It will find the appropriate exporter and use it to 
+		 * export the object.
+		 * @param exporter	Root object for the export
+		 * @param flowElement	Element to export
+		 * @return XMLList	XML for the flowElement
+		 */
+		public function exportChild(flowElement:FlowElement):XMLList
+		{
+			var className:String = flash.utils.getQualifiedClassName(flowElement);
+			var info:FlowElementInfo = _config.lookupByClass(className);
+			if (info != null)
+				return info.exporter(this, flowElement);
+			return null;
+		}
+				
+		private function exportObjectAsDictionary(key:String,styleDict:Object):XMLList
+		{
+			// link attributes only right now
+			if (key != LinkElement.LINK_NORMAL_FORMAT_NAME && key != LinkElement.LINK_ACTIVE_FORMAT_NAME && key != LinkElement.LINK_HOVER_FORMAT_NAME)
+				return null;
+
+			// create the TextLayoutFormat element
+			var elementName:String = "TextLayoutFormat";
+			var formatXML:XML = <{elementName}/>;
+			formatXML.setNamespace(flowNS);
+			exportStyles(XMLList(formatXML), styleDict, formatDescription);
+
+			// create the link format element
+			var linkFormatXML:XMLList = XMLList(<{key}/>);
+			linkFormatXML.appendChild(formatXML);
+			return linkFormatXML;
+		}
+		
+		/** Helper function to export styles (core or user) in the form of xml attributes or xml children
+		 *
+		 * @param xml object to which attributes/children are added 
+		 * @styles the styles object: core styles, user styles, or a style dictionary 
+		 * @param description attribute class metadata object; must be specified for core styles, not otherwise
+		 * @param exclusions values to be excluded from being exported
+		 */
+		protected function exportStyles(xml:XMLList, styles:Object, description:Object=null, exclusions:Array=null):void
+		{
+			var sortableStyles:Array = [];
+			for (var key:Object in styles)
+			{
+				var val:Object = styles[key];
+				if (!exclusions || exclusions.indexOf(val) == -1)
+				{
+					if (description)
+					{
+						// Core style
+						// Use the description object to filter out styles that should not be exported
+						// and to obtain the corresponding String to be used as an XML attribute value
+						var prop:Property = description[key];
+						if (prop)
+							sortableStyles.push({xmlName:key, xmlVal:prop.toXMLString(val)});
+					}
+					else
+					{
+						// User style
+						if ((val is String) || val.hasOwnProperty("toString"))
+						{
+							// Is or can be converted to a String which will be used as an XML attribute value
+							sortableStyles.push({xmlName:key, xmlVal:val});
+						}
+						else
+						{
+							// A style dictionary; Will be converted to an XMLList containing elements to be added as children 
+							var customDictProp:XMLList = exportObjectAsDictionary(key as String,val);
+							if (customDictProp)
+								sortableStyles.push({xmlName:key, xmlVal:customDictProp});
+						}
+						
+					}
+				}
+			}
+			
+			// Sort the styles based on name for predictable export order
+			sortableStyles.sortOn("xmlName");
+			
+			for each(var exportInfo:Object in sortableStyles)
+            {
+            	var xmlVal:Object = exportInfo.xmlVal;
+            	if (xmlVal is String)
+					xml.@[exportInfo.xmlName] = xmlVal; // as an attribute
+				else if (xmlVal is XMLList)
+					xml.appendChild(xmlVal);			// as a child 
+            }  
+		}
+
+		internal function get flowNS():Namespace
+		{
+			return _ns;
+		}
+
+		protected function get formatDescription():Object
+		{
+			return null;
+		}		
+
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
new file mode 100755
index 0000000..8eaa1be
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/BaseTextLayoutImporter.as
@@ -0,0 +1,606 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion 
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.BreakElement;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/**
+	 * @private  
+	 * BaseTextLayoutImportFilter is a base class for handling the import/export of TextLayout text in the native format.
+	 */ 
+	internal class BaseTextLayoutImporter implements ITextImporter
+	{	
+		private var _ns:Namespace;		// namespace of expected in imported/exported content
+		
+		private var _errors:Vector.<String>;
+		private var _textFlowNamespace:Namespace; // namespace of the TextFlow element against which the namespaces of the following elements are validated
+		
+		private var _throwOnError:Boolean;
+		
+		protected var _config:ImportExportConfiguration;
+		protected var _textFlowConfiguration:IConfiguration;
+		
+		// static private const anyPrintChar:RegExp = /[^\s]/g;
+		// Consider only tab, line feed, carriage return, and space as characters used for pretty-printing. 
+		// While debatable, this is consistent with what CSS does. 
+		static private const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g; 
+
+		public function BaseTextLayoutImporter(textFlowConfiguration:IConfiguration, nsValue:Namespace, config:ImportExportConfiguration)
+		{
+			_textFlowConfiguration = textFlowConfiguration;
+			_ns = nsValue;
+			_config = config;
+		}
+		
+		protected function clear():void
+		{
+			if (errors)
+				errors.splice(0, errors.length);
+			_textFlowNamespace = null;
+			_impliedPara = null;
+		}
+		
+		/** Import text content, from an external source, and convert it into a TextFlow.
+		 * @param source		source data to convert, may be string or XML
+		 * @return TextFlow that was created from the source.
+		 */
+		public function importToFlow(source:Object):TextFlow
+		{
+			clear();		// empty results of previous imports
+			
+			if (_throwOnError)
+				return importToFlowCanThrow(source);
+			
+			var rslt:TextFlow = null;
+			var savedErrorHandler:Function = Property.errorHandler;
+			try
+			{
+				Property.errorHandler = importPropertyErrorHandler;
+				rslt = importToFlowCanThrow(source);
+			}
+			catch (e:Error)
+			{
+				reportError(e.toString());
+			}
+			Property.errorHandler = savedErrorHandler;
+			return rslt;
+		}
+		
+		/** @private */
+		protected function importPropertyErrorHandler(p:Property,value:Object):void
+		{
+			reportError(Property.createErrorString(p,value));
+		}
+		
+		private function importToFlowCanThrow(source:Object):TextFlow
+		{
+			if (source is String)
+				return importFromString(String(source));
+			else if (source is XML)
+				return importFromXML(XML(source));
+			return null;
+		}
+		
+		/** Parse and convert input data.
+		 * 
+		 * @param source - a string which is in XFL format. String is applied to an XML object then passed
+		 * to importFromXML to be processed.  The source must be capable of being cast as an XML
+		 * object (E4X). 
+		 */
+		protected function importFromString(source:String):TextFlow
+		{
+			var originalSettings:Object = XML.settings();
+			try
+			{
+				XML.ignoreProcessingInstructions = false;		
+				XML.ignoreWhitespace = false;
+				var xmlTree:XML = new XML(source);				
+			}			
+			finally
+			{
+				XML.setSettings(originalSettings);
+			}	
+			
+			return importFromXML(xmlTree);
+		}
+		
+		/** Parse and convert input data.
+		 * 
+		 * xflSource is a XFL formated object which must be capable of being cast as an XML
+		 * object (E4X). 
+		 */
+		protected function importFromXML(xmlSource:XML):TextFlow
+			// Parse an XFL hierarchy into a TextFlow, using the geometry supplied by a TextFrame
+			// to host child containers (e.g. tables). This is the main entry point into this class.
+		{
+			return parseContent(xmlSource[0]);
+		}
+		
+		// This routine imports a TextFlow
+		protected function parseContent(rootStory:XML):TextFlow
+		{
+			// If the root element isn't a textFlow we know how to parse, keep descending the hierarchy.
+			var child:XML = rootStory..*::TextFlow[0];
+			if (child)
+				return parseTextFlow(this, rootStory);
+			return null;
+		}
+		
+		/** Returns the namespace used in for writing XML/XFL
+		 * 
+		 * @return the Namespace being used.
+		 */
+		public function get ns(): Namespace
+		{
+			return _ns;
+		}
+		
+		// Remove double spaces, tabs, and newlines.
+		// If I have a sequence of different sorts of spaces (e.g., en quad, hair space), would I want them converted down to one space? Probably not.
+		// For now, u0020 is the only space character we consider for eliminating duplicates, though u00A0 (non-breaking space) is potentially eligible. 
+		static private const dblSpacePattern:RegExp = /[\u0020]{2,}/g;
+		// Tab, line feed, and carriage return
+		static private const tabNewLinePattern:RegExp = /[\u0009\u000a\u000d]/g;
+		protected static function stripWhitespace(insertString:String):String
+		{
+			// Replace the newlines and tabs inside the element with spaces.
+			return insertString.replace(tabNewLinePattern, " ");
+		}
+
+		/** Parse XML and convert to  TextFlow. 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent always null - this parameter is only provided to match FlowElementInfo.importer signature
+		 * @return TextFlow	the new TextFlow created as a result of the parse
+		 */
+		static public function parseTextFlow(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:Object=null):TextFlow
+		{
+			return importFilter.createTextFlowFromXML(xmlToParse, null);
+		}		
+		
+		/** Static method to parse the supplied XML into a paragrph. Parse the <p ...> tag and it's children.
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parsePara(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var paraElem:ParagraphElement = importFilter.createParagraphFromXML(xmlToParse);
+			if (importFilter.addChild(parent, paraElem))
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, paraElem);
+				//if parsing an empty paragraph, create a Span for it.
+				if (paraElem.numChildren == 0)
+					paraElem.addChild(new SpanElement());
+			}
+		}
+		
+		static protected function copyAllStyleProps(dst:FlowLeafElement,src:FlowLeafElement):void
+		{
+			dst.format = src.format;
+			dst.styleName       = src.styleName;
+			dst.userStyles      = src.userStyles;
+			dst.id              = src.id;
+		}
+		
+		/** Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
+		 * Insert the span into its parent
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseSpan(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var firstSpan:SpanElement = importFilter.createSpanFromXML(xmlToParse);
+			
+			var elemList:XMLList = xmlToParse[0].children();
+			if(elemList.length() == 0)
+			{
+				// Empty span, but may have formatting, so don't strip it out. 
+				// Note: the normalizer may yet strip it out if it is not the last child, but that's the normalizer's business.
+				importFilter.addChild(parent, firstSpan); 
+				return;
+			}
+	
+			for each (var child:XML in elemList) 
+			{
+				var elemName:String = child.name() ? child.name().localName : null;
+					
+				if (elemName == null) // span text
+				{
+					if (firstSpan.parent == null)	// hasn't been used yet
+					{
+						firstSpan.text = child.toString();
+						importFilter.addChild(parent, firstSpan);
+					}
+					else
+					{
+						var s:SpanElement = new SpanElement();
+						copyAllStyleProps(s,firstSpan);
+						s.text = child.toString();
+						importFilter.addChild(parent, s);
+					}
+				}
+				else if (elemName == "br")
+				{
+					var brElem:BreakElement = importFilter.createBreakFromXML(child);	// may be null
+					if (brElem)
+					{
+						copyAllStyleProps(brElem,firstSpan);
+						importFilter.addChild(parent, brElem);
+					}
+					else
+						importFilter.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));
+				}
+				else if (elemName == "tab")
+				{
+					var tabElem:TabElement = importFilter.createTabFromXML(child);	// may be null
+					if (tabElem)
+					{
+						copyAllStyleProps(tabElem,firstSpan);
+						importFilter.addChild(parent, tabElem);
+					}
+					else
+						importFilter.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));
+				}
+				else
+					importFilter.reportError(GlobalSettings.resourceStringFunction("unexpectedXMLElementInSpan",[ elemName ]));				
+			}
+		}
+		
+		/** Static method for constructing a break element from XML. Validate the <br> ... </br> tag. 
+		 * Use "\u2028" as the text; Insert the new element into its parent 
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseBreak(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var breakElem:BreakElement = importFilter.createBreakFromXML(xmlToParse);
+			importFilter.addChild(parent, breakElem);
+		}
+
+		
+		/** Static method for constructing a tab element from XML. Validate the <tab> ... </tab> tag. 
+		 * Use "\t" as the text; Insert the new element into its parent 
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseTab(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var tabElem:TabElement = importFilter.createTabFromXML(xmlToParse);	// may be null
+			if (tabElem)
+				importFilter.addChild(parent, tabElem);
+		}
+		
+		protected function checkNamespace(xmlToParse:XML):Boolean
+		{
+			var elementNS:Namespace = xmlToParse.namespace();
+			if (!_textFlowNamespace) // Not set yet; must be parsing the TextFlow element
+			{
+				// TextFlow element: allow only empty namespace and flow namespace
+				if (elementNS != ns) 
+				{
+					reportError(GlobalSettings.resourceStringFunction("unexpectedNamespace", [elementNS.toString()]));
+					return false;
+				}
+				_textFlowNamespace = elementNS;
+			}
+			// Other elements: must match the namespace of the TextFlow element
+			// Specifically, can't be empty unless the TextFlow element's namespace is also empty 
+			else if (elementNS != _textFlowNamespace) 
+			{
+				reportError(GlobalSettings.resourceStringFunction("unexpectedNamespace", [elementNS.toString()]));
+				return false;
+			}
+			
+			return true;
+		}
+		
+		public function parseAttributes(xmlToParse:XML,formatImporters:Array):void
+		{
+			var importer:IFormatImporter;
+			// reset them all
+			for each (importer in formatImporters)
+				importer.reset();
+			
+			for each (var item:XML in xmlToParse.attributes())
+			{
+				var propertyName:String = item.name().localName;
+				var propertyValue:String = item.toString();
+				var imported:Boolean = false;
+				for each (importer in formatImporters)
+				{
+					if (importer.importOneFormat(propertyName,propertyValue))
+					{
+						imported = true;
+						break;
+					}
+				}
+				if (!imported)	// not a supported attribute
+					handleUnknownAttribute (xmlToParse.name().localName, propertyName);}
+		}
+				
+		static protected function extractAttributesHelper(curAttrs:Object, importer:TLFormatImporter):Object
+		{
+			if (curAttrs == null)
+				return importer.result;
+			
+			if (importer.result == null)
+				return curAttrs;
+				
+			var workAttrs:Object = new importer.classType(curAttrs);
+			workAttrs.apply(importer.result);
+			return workAttrs;
+		}	
+		
+		/** Parse XML and convert to  TextFlow.
+		 * @param xmlToParse	content to parse
+		 * @param textFlow 		TextFlow we're parsing. If null, create or find a new TextFlow based on XML content
+		 * @return TextFlow	the new TextFlow created as a result of the parse
+		 */
+		public function createTextFlowFromXML(xmlToParse:XML, newFlow:TextFlow = null):TextFlow
+		{
+			CONFIG::debug { assert(false,"missing override for createTextFlowFromXML"); }
+			return null;
+		}
+		
+		public function createParagraphFromXML(xmlToParse:XML):ParagraphElement
+		{
+			CONFIG::debug { assert(false,"missing override for createParagraphFromXML"); }
+			return null;
+		}
+		
+		public function createSpanFromXML(xmlToParse:XML):SpanElement
+		{
+			CONFIG::debug { assert(false,"missing override for createSpanFromXML"); }
+			return null;
+		}
+		
+		public function createBreakFromXML(xmlToParse:XML):BreakElement
+		{
+			parseAttributes(xmlToParse,null);	// no attributes allowed - reports errors
+			return new BreakElement();
+		}
+		
+		public function createTabFromXML(xmlToParse:XML):TabElement
+		{
+			parseAttributes(xmlToParse,null);	// reports errors
+			return new TabElement();
+		}
+		
+		/** Parse XML, convert to FlowElements and add to the parent.
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		public function parseFlowChildren(xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			parseFlowGroupElementChildren(xmlToParse, parent);
+		}
+		
+		/** Parse XML, convert to FlowElements and add to the parent.
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element) 
+		 */
+		public function parseFlowGroupElementChildren(xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object = null, chainedParent:Boolean=false):void
+		{
+			for each (var child:XML in xmlToParse.children())
+			{
+				if (child.nodeKind() == "element")
+				{
+					parseObject(child.name().localName, child, parent, exceptionElements);
+				}
+				// look for mixed content here
+ 				else if (child.nodeKind() == "text") 
+ 				{
+ 					var txt:String = child.toString();
+ 					// Strip whitespace-only text appearing as a child of a container-formatted element
+ 					var strip:Boolean = false;
+ 					if (parent is ContainerFormattedElement)
+ 					{
+						strip = txt.search(anyPrintChar) == -1;
+					}
+					
+ 					if (!strip) 
+ 					{
+						// note, we don't want to set the paraFormat so that we inherit them from the TextFlow
+						var span:SpanElement = new SpanElement();
+						span.text = txt;
+						addChild(parent, span);
+					}
+				}
+			}
+			
+			// no implied paragraph should extend across container elements
+			if (!chainedParent && parent is ContainerFormattedElement)
+				resetImpliedPara();
+		}
+			
+		public function createParagraphFlowFromXML(xmlToParse:XML, newFlow:TextFlow = null):TextFlow
+		{
+			CONFIG::debug { assert(false,"missing override for createParagraphFlowFromXML"); }	// client must override
+			return null;
+		}
+		
+		tlf_internal function parseObject(name:String, xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object=null):void
+		{
+			if (!checkNamespace(xmlToParse))
+				return;
+
+			var info:FlowElementInfo = _config.lookup(name);
+			if (!info)
+			{
+				if (exceptionElements == null || exceptionElements[name] === undefined)
+					handleUnknownElement (name, xmlToParse, parent);		
+			}
+			else
+				info.parser(this, xmlToParse, parent);
+		}
+		
+		protected function handleUnknownElement(name:String, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			reportError(GlobalSettings.resourceStringFunction("unknownElement", [ name ]));	
+		}
+		
+		protected function handleUnknownAttribute(elementName:String, propertyName:String):void
+		{
+			reportError(GlobalSettings.resourceStringFunction("unknownAttribute", [ propertyName, elementName ]));	
+		}
+		
+		protected function getElementInfo(xmlToParse:XML):FlowElementInfo
+		{
+			return _config.lookup(xmlToParse.name().localName);
+		}
+		
+		protected function GetClass(xmlToParse:XML):Class
+		{
+			var info:FlowElementInfo = _config.lookup(xmlToParse.name().localName);
+			return info ? info.flowClass : null;
+		}
+		
+		// In the text model, non-FlowParagraphElements (i.e. spans, images, links, TCY) cannot be children of a ContainerElement (TextFlow, Div etc.)
+		// They can only be children of paragraphs or subparagraph blocks. 
+		// In XML, however, <p> elements can be implied (for example, a <span> may appear as a direct child of <flow>).  
+		// So, while parsing the XML, if we enounter a non-FlowParagraphElement child of a ContainerElement 
+		// 1. an explicitly created paragraph is used as the parent instead
+		// 2. such explicitly created paragraphs are shared by adjacent flow elements provided there isn't an intervening FlowParagraphElement		
+		private var _impliedPara:ParagraphElement = null; 
+		
+		/** @private */
+		tlf_internal function createImpliedParagraph():ParagraphElement
+		{
+			return createParagraphFromXML(<p/>);
+		}
+		
+		/**
+		 * @private
+		 * Helper function for adding a child flow element that honors throwOnError setting and uses the parent override
+		 * NOTE: You MUST NOT call addChild directly unless you are sure
+		 * - There is not possibility of an implied paragraph, and
+		 * - Parent is of type that can contain child
+		*/
+		tlf_internal function addChild(parent:FlowGroupElement, child:FlowElement):Boolean
+		{
+			if (child is ParagraphFormattedElement)
+			{
+				// Reset due to possibly intervening FlowParagrahElement; See note 2. above
+				resetImpliedPara();
+			}
+			else if (parent is ContainerFormattedElement)
+			{
+				// See note 1. above
+				if (!_impliedPara)
+				{
+					// Derived classes may have special behavior for <p> tags. Implied paragraphs may need the same behavior.
+					// So call createParagraphFromXML, don't just instantiate a ParagraphElement 
+					_impliedPara = createImpliedParagraph();
+					parent.addChild(_impliedPara);
+				}
+				
+				parent = _impliedPara;
+			}	
+			
+			if (_throwOnError)
+				parent.addChild(child);
+			else
+			{
+				try
+				{
+					parent.addChild(child);
+				}
+				catch (e:*)
+				{
+					reportError(e); 	
+					return false;
+				}
+			}
+			
+			return true;
+		} 
+		
+		tlf_internal function resetImpliedPara():void
+		{
+			if (_impliedPara)
+			{
+				onResetImpliedPara(_impliedPara);
+				_impliedPara = null;
+			}
+		}
+		
+		protected function onResetImpliedPara(para:ParagraphElement):void
+		{
+		}
+
+		/** Errors encountered while parsing. 
+		 * Value is a vector of Strings.
+		 */
+		public function get errors():Vector.<String>
+		{
+			return _errors;
+		}
+		
+		/** Errors will cause exceptions if throwOnError is true. */
+		public function get throwOnError():Boolean
+		{
+			return _throwOnError;
+		}
+		public function set throwOnError(value:Boolean):void
+		{
+			_throwOnError = value;
+		}
+		
+		/** Register an error that was encountered while parsing. If throwOnError
+		 * is true, the error causes an exception. Otherwise it is logged and parsing
+		 * continues.
+		 * @param error	the String that describes the error
+		 */
+		protected function reportError(error:String):void
+		{
+			if (_throwOnError)
+				throw new Error(error);
+			
+			if (!_errors)
+				_errors = new Vector.<String>();
+			_errors.push(error);
+		}
+	}
+}
+
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/ConversionType.as b/textLayout_conversion/src/flashx/textLayout/conversion/ConversionType.as
new file mode 100755
index 0000000..0139335
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/ConversionType.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	/**
+	 * Values for the format of exported text.
+	 * The values <code>STRING_TYPE</code> and <code>XML_TYPE</code> 
+	 * can be used for the <code>conversionType</code> parameter for 
+	 * the export() method in the ITextExporter interface and the
+	 * TextConverter class.
+	 *
+	 * @see flashx.textLayout.conversion.ITextExporter#export()
+	 * @see flashx.textLayout.conversion.TextConverter#export()
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class ConversionType
+	{
+		/** 
+		 * Export as type String. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public static const STRING_TYPE:String = "stringType";		
+		/** 
+		 * Export as type XML.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public static const XML_TYPE:String = "xmlType";				
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/CustomFormatImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/CustomFormatImporter.as
new file mode 100755
index 0000000..aafa829
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/CustomFormatImporter.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 flashx.textLayout.conversion
+{
+	import flash.utils.Dictionary;
+	
+	[ExcludeClass]
+	/**
+	 * @private  
+	 */
+	internal class CustomFormatImporter implements IFormatImporter
+	{
+		private var _rslt:Dictionary = null;
+		
+		public function CustomFormatImporter()
+		{ }
+		public function reset():void
+		{ _rslt = null; }
+		public function get result():Object
+		{ return _rslt; }
+		public function importOneFormat(key:String,val:String):Boolean
+		{
+			if (_rslt == null)
+				_rslt = new Dictionary();
+			_rslt[key] = val;
+			return true; 
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/FlowElementInfo.as b/textLayout_conversion/src/flashx/textLayout/conversion/FlowElementInfo.as
new file mode 100755
index 0000000..f570c8f
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/FlowElementInfo.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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.conversion
+{
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	
+	[ExcludeClass]
+	/**
+	 * @private  
+	 * Contains configuration data about FlowElement types. 
+	 */
+	internal class FlowElementInfo
+	{
+		/** Class used for the FlowElement sub-type */
+		private var _flowClass:Class;
+		/** Fully qualified class name */
+		private var _flowClassName:String;
+		/** Parsing function used for reading in data on a FlowElement instance */
+		private var _parser:Function;
+		/** Class for the object's XFL import/export interface */
+		private var _exporter:Function;
+		
+		/** is this class a ParagraphFormattedElement */
+		private var _isParagraphFormattedElement:Boolean;
+		
+		/** Construct a FlowElementInfo
+		 * @param	flowClass	Class used to represent the FlowElement
+		 * @param 	parser		Function used for parsing XML description of a FlowElement
+		 * @param 	exporter	Class used to represent the FlowElement's exporter
+		 * @param	isParagraphFormattedElement Boolean indicating if this class is a subclass of ParagraphFormattedElement
+		 */
+		public function FlowElementInfo(flowClass:Class, parser:Function, exporter:Function , isParagraphFormattedElement:Boolean)
+		{
+			this._flowClass = flowClass;
+			this._parser = parser;
+			this._exporter = exporter;
+			this._flowClassName = getQualifiedClassName(flowClass);
+			this._isParagraphFormattedElement = isParagraphFormattedElement;
+			CONFIG::debug {
+				if (flowClass == null)
+					assert(isParagraphFormattedElement == false,"Bad value supplied for isParagraphFormattedElement"); 
+				else
+					assert(isParagraphFormattedElement == ((new flowClass) is ParagraphFormattedElement),"Bad value supplied for isParagraphFormattedElement"); 
+			}
+		}
+		
+		/** Class used for the FlowElement sub-type */
+		public function get flowClass():Class
+		{ return _flowClass; }
+		/** Fully qualified class name */
+		public function get flowClassName():String
+		{ return _flowClassName; }
+		/** Parsing function used for reading in data on a FlowElement instance */
+		public function get parser():Function
+		{ return _parser; }
+		/** Class for the object's XFL import/export interface */
+		public function get exporter():Function
+		{ return _exporter; }
+		/** Boolean indicating if flowClass is a subclass of ParagraphFormattedElement */
+		public function get isParagraphFormattedElement():Boolean
+		{ return _isParagraphFormattedElement; }
+	}
+}
\ No newline at end of file
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/HtmlExporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/HtmlExporter.as
new file mode 100755
index 0000000..2647a9c
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/HtmlExporter.as
@@ -0,0 +1,468 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.*;
+	import flashx.textLayout.formats.TabStopFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextAlign;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.LeadingModel;
+	import flashx.textLayout.formats.FormatValue;
+	import flash.text.engine.FontWeight;
+	import flash.text.engine.FontPosture;
+	import flash.text.engine.Kerning;
+	import flash.text.engine.TabAlignment;
+	import flash.utils.getQualifiedClassName;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.formats.FormatValue;
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** 
+	* @private
+	* Export filter for HTML format. 
+	*/
+	internal class HtmlExporter implements ITextExporter	
+	{
+		private static var _config:ImportExportConfiguration;
+		
+		public function HtmlExporter()
+		{
+			if (!_config)
+			{
+				_config = new ImportExportConfiguration();
+				_config.addIEInfo("P", ParagraphElement, null, exportParagraph, true);
+				_config.addIEInfo("A", LinkElement, null, exportLink, false);
+				_config.addIEInfo("TCY" /* only children exported, so name is irrelevant */, TCYElement, null, exportTCY, false);
+				_config.addIEInfo("SPAN"/* only children exported, so name is irrelevant */, SpanElement, null, exportSpan, false);
+				_config.addIEInfo("IMG", InlineGraphicElement, null, exportImage, false);
+				_config.addIEInfo("TAB" /* exported as a span, so name is irrelevant */, TabElement, null, exportTab, false);
+				_config.addIEInfo("BR", BreakElement, null, exportBreak, false);
+
+			}
+		}
+		 
+		/** Export text content
+		 * @param source	the text to export
+		 * @param conversionType 	what type to return
+		 * @return Object	the exported content
+		 */
+		public function export(source:TextFlow, conversionType:String):Object
+		{
+			if (conversionType == ConversionType.STRING_TYPE)
+				return exportToString(source);
+			else if (conversionType == ConversionType.XML_TYPE)
+				return exportToXML(source);
+			return null;
+		}
+		
+		/** Export text content as a string
+		 * @param source	the text to export
+		 * @return String	the exported content
+		 */
+		private function exportToString(textFlow:TextFlow):String
+		{
+			var result:String;
+			// We do some careful type casting here so that leading and trailing spaces in the XML don't
+			// get dropped when it is converted to a string
+			var originalSettings:Object = XML.settings();
+			try
+			{
+				XML.ignoreProcessingInstructions = false;		
+				XML.ignoreWhitespace = false;
+				XML.prettyPrinting = false;
+				result = exportToXML(textFlow).toXMLString();
+				XML.setSettings(originalSettings);
+			}
+			catch(e:Error)
+			{
+				XML.setSettings(originalSettings);
+				throw(e);
+			}		
+			return result;
+		}
+		
+		/** Export text content of a TextFlow into HTML format.
+		 * @param source	the text to export
+		 * @return XML	the exported content
+		 */
+		private function exportToXML(textFlow:TextFlow) : XML
+		{
+			var xml:XML = <BODY/>;
+			
+			var firstLeaf:FlowLeafElement = textFlow.getFirstLeaf();
+			if (firstLeaf)
+			{
+				var para:ParagraphElement = firstLeaf.getParagraph();	
+				var lastPara:ParagraphElement = textFlow.getLastLeaf().getParagraph();
+	
+				for (;;)
+				{
+					xml.appendChild(exportElement(para));
+					if (para == lastPara)
+						break;
+						
+					para = textFlow.findLeaf(para.getAbsoluteStart() + para.textLength).getParagraph();
+				}
+			}
+			
+			var html:XML = <HTML/>;
+			html.appendChild(xml);
+			
+			return html;
+		}
+		
+		/** Export a paragraph
+		 * @param name name for the XML element
+		 * @return XML	the populated XML element
+		 */
+		private function exportParagraph(name:String, para:ParagraphElement):XML
+		{
+			// Exported as a <P/>
+			// Some paragraph-level formats (such as textAlign) are exported as attributes of <P/>, 
+			// Others (such as textIndent) are exported as attributes of the <TEXTFORMAT/> parent of <P/>
+			// Some character-level formats (such as fontSize) are exported as attributes of the <FONT/> child of <P/>
+			// Children of the ParagraphElement are nested inside the <FONT/>
+			
+			var xml:XML = <{name}/>;
+			
+			var fontXML:XML = exportFont(para.computedFormat);
+			CONFIG::debug { assert(fontXML != null, "Expect exportFont to return non-null xml if second parameter (ifDifferentFromFormat) is null"); }
+			exportChildren (fontXML, para);
+			nest(xml, fontXML);
+			
+			return exportParagraphFormat(xml, para);
+		}
+		
+		/** Export a link
+		 * @param name name for the XML element
+		 * @return XML	the populated XML element
+		 */
+		private function exportLink(name:String, link:LinkElement):Object
+		{
+			// Exported as an <A/> with HREF and TARGET attributes
+			// Children of the LinkElement are nested inside the <A/>
+			// If the computed values of certain character-level formats differ from the corresponding computed values for the
+			// containing paragraph, these are exported as attributes of a <FONT/> which (in this case) parents the <A/>.
+			
+			var xml:XML = <{name}/>;
+			
+			if (link.href)
+				xml.@HREF= link.href;
+			if (link.target)
+				xml.@TARGET = link.target;
+			else
+			{
+				// TextField uses _self as the default target  
+				// while TLF uses null (funcionally identical to _blank). Account for this difference.
+				xml.@TARGET = "_blank";
+			}
+						
+			exportChildren(xml, link);
+			
+			var format:ITextLayoutFormat = link.computedFormat;
+			var ifDifferentFromFormat:ITextLayoutFormat = link.getParagraph().computedFormat;
+			
+			var font:XML = exportFont(format, ifDifferentFromFormat);	
+			return font ? nest(font, xml) : xml;
+		}
+		
+		/** Export a tcy element
+		 * @param name ignored
+		 * @return XMLList the exported children
+		 */
+		private function exportTCY(name:String, tcy:TCYElement):XMLList
+		{
+			// Only children are exported
+			
+			var xml:XML = <{name}/>;
+			exportChildren(xml, tcy);
+			return xml.children();
+		}
+		
+		static private const brRegEx:RegExp = /\u2028/;
+		
+		/** Gets the xml element used to represent a character in the export format
+		 */
+		static private function getSpanTextReplacementXML(ch:String):XML
+		{
+			CONFIG::debug {assert(ch == '\u2028', "Did not recognize character to be replaced with XML"); }
+			return <BR/>;
+		}
+		
+		/** Export a span
+		 * @param name name for the XML element
+		 * @return XML	the populated XML element
+		 */
+		private function exportSpan(name:String, span:SpanElement):Object
+		{
+			// Span text is exported as a text node (or text nodes delimited by <BR/> elements for any occurences of U+2028)
+			// These text nodes and <BR/> elements are optionally nested in formatting elements
+			var xml:XML  = <{name}/>; 
+			BaseTextLayoutExporter.exportSpanText(xml, span, brRegEx, getSpanTextReplacementXML);
+			
+			// for brevity, do not export attribute-less <span> tags; export just their children
+			var children:Object = xml.children();
+				
+			// Workaround for bug 1852072 : extraneous tags can appear around a string child added after an XML element 
+			if (children.length() == 1 && children[0].nodeKind() == "text")
+				children = xml.text()[0];
+					
+			return exportSpanFormat (children, span);
+		}
+		
+		/** Export an inline graphic
+		 * @param name name for the XML element
+		 * @return XML	the populated XML element
+		 */
+		private function exportImage(name:String, image:InlineGraphicElement):XML
+		{
+			// Exported as an <IMG/> with SRC, WIDTH, HEIGHT and ALIGN attributes
+			
+			var xml:XML = <{name}/>;
+			if (image.id)
+				xml.@ID = image.id;
+			if (image.source)
+				xml.@SRC = image.source;
+			if (image.width !== undefined && image.width != FormatValue.AUTO) 
+				xml.@WIDTH = image.width;
+			// xml.@WIDTH = image.actualWidth;
+			if (image.height !== undefined && image.height != FormatValue.AUTO) 
+				xml.@HEIGHT = image.height;
+			// xml.@HEIGHT = image.actualHeight;	
+			if (image.float != Float.NONE)
+				xml.@ALIGN = image.float;
+			return xml;
+		}
+	
+		/** Export a break
+		 * Is this ever called: BreakElements are either merged with adjacent spans or become spans? 
+		 * @param name name for the XML element
+		 * @return XML	the populated XML element
+		 */		
+		private function exportBreak(name:String, breakElement:BreakElement):XML
+		{
+			return <{name}/>;
+		}
+		
+		/** Export a tab
+		 * Is this ever called: TabElements are either merged with adjacent spans or become spans? 
+		 * @param name ignored
+		 * @return XML	the populated XML element
+		 */	
+		private function exportTab(name:String, tabElement:TabElement):Object
+		{
+			// Export as a span
+			return exportSpan(name, tabElement);
+		}
+		
+		private function exportTextFormatAttribute (textFormatXML:XML, attrName:String, attrVal:*):XML
+		{
+			if (!textFormatXML)
+				textFormatXML = <TEXTFORMAT/>;
+				
+			textFormatXML.@[attrName] = attrVal;
+			
+			return textFormatXML;	
+		}
+		
+		/** Exports the paragraph-level format for a paragraph  
+		 * @param xml xml to decorate with attributes or add nest in formatting elements
+		 * @para the paragraph
+		 * @return XML	the outermost XML element after exporting 
+		 */	
+		private function exportParagraphFormat(xml:XML, para:ParagraphElement):XML
+		{	
+			var paraFormat:ITextLayoutFormat = para.computedFormat;
+			
+			var textAlignment:String;
+			switch(paraFormat.textAlign)
+			{
+				case TextAlign.START:
+					textAlignment = (paraFormat.direction == Direction.LTR) ? TextAlign.LEFT : TextAlign.RIGHT;
+					break;
+				case TextAlign.END:
+					textAlignment = (paraFormat.direction == Direction.LTR) ? TextAlign.RIGHT : TextAlign.LEFT;
+					break;
+				default:
+					textAlignment = paraFormat.textAlign;
+			}
+			xml.@ALIGN = textAlignment;
+					
+			var textFormat:XML;
+			
+			if (paraFormat.paragraphStartIndent != 0)
+				textFormat = exportTextFormatAttribute (textFormat, paraFormat.direction == Direction.LTR ? "LEFTMARGIN" : "RIGHTMARGIN", paraFormat.paragraphStartIndent);
+			
+			if (paraFormat.paragraphEndIndent != 0)
+				 textFormat = exportTextFormatAttribute (textFormat, paraFormat.direction == Direction.LTR ? "RIGHTMARGIN" : "LEFTMARGIN", paraFormat.paragraphEndIndent);
+			
+			if (paraFormat.textIndent != 0)
+				textFormat = exportTextFormatAttribute(textFormat, "INDENT", paraFormat.textIndent);
+				
+			if (paraFormat.leadingModel == LeadingModel.APPROXIMATE_TEXT_FIELD)
+			{
+				var firstLeaf:FlowLeafElement = para.getFirstLeaf();
+				if (firstLeaf)
+				{
+					var lineHeight:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(firstLeaf.computedFormat.lineHeight,firstLeaf.getEffectiveFontSize());
+					if (lineHeight != 0)
+						textFormat = exportTextFormatAttribute(textFormat, "LEADING", lineHeight);
+				}
+			}
+			
+			var tabStops:Array = paraFormat.tabStops;
+			if (tabStops)
+			{
+				var tabStopsString:String = "";
+				for each (var tabStop:TabStopFormat in tabStops)
+				{
+					if (tabStop.alignment != TabAlignment.START)
+						break;
+					
+					if (tabStopsString.length)
+						tabStopsString += ", ";
+					
+					tabStopsString += tabStop.position;
+				}
+				
+				if (tabStopsString.length)
+					textFormat = exportTextFormatAttribute(textFormat, "TABSTOPS", tabStopsString);
+			}
+			
+			return textFormat ? nest(textFormat, xml) : xml;
+		}
+		
+		/** Exports the character-level format for a span  
+		 * @param xml xml/xmlList to nest in formatting elements
+		 * @span the span
+		 * @return XML	the outermost XML element after exporting 
+		 */	
+		private function exportSpanFormat(xml:Object, span:SpanElement):Object
+		{
+			// These are optionally nested in a <FONT/> with appopriate attributes ,			 
+			
+			var format:ITextLayoutFormat = span.computedFormat;
+			var outerElement:Object = xml;
+			
+			// Nest in <B/>, <I/>, or <U/> if applicable
+			if (format.textDecoration.toString() == flashx.textLayout.formats.TextDecoration.UNDERLINE)
+				outerElement = nest (<U/>, outerElement);
+			if (format.fontStyle.toString() == flash.text.engine.FontPosture.ITALIC)
+				outerElement = nest (<I/>, outerElement);
+			if (format.fontWeight.toString() == flash.text.engine.FontWeight.BOLD)
+				outerElement = nest (<B/>, outerElement);
+				
+			// Nest in <FONT/> if the computed values of certain character-level formats 
+			// differ from the corresponding computed values for the containing parent that's exported
+			// A span can be contained in a TCY, link, or paragraph. Of these, TCY is not exported, so only
+			// check link and paragraph.
+			var exportedParent:FlowElement = span.getParentByType(LinkElement);
+			if (!exportedParent)
+				exportedParent = span.getParagraph();
+	
+			var font:XML = exportFont(format, exportedParent.computedFormat);	
+			if (font)
+				outerElement = nest(font, outerElement);	
+
+			return outerElement;			   	
+		}	
+		
+		private function exportFontAttribute (fontXML:XML, attrName:String, attrVal:*):XML
+		{
+			if (!fontXML)
+				fontXML = <FONT/>;
+				
+			fontXML.@[attrName] = attrVal;
+			
+			return fontXML;	
+		}
+		
+		/**  
+		 * Exports certain character level formats as a <FONT/> with appropriate attributes
+		 * @param format format to export
+		 * @param ifDifferentFromFormat if non-null, a value in format is exported only if it differs from the corresponding value in ifDifferentFromFormat
+		 * @return XML	the populated XML element
+		 */	
+		private function exportFont(format:ITextLayoutFormat, ifDifferentFromFormat:ITextLayoutFormat=null):XML
+		{
+			var font:XML;
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.fontFamily != format.fontFamily)
+				font = exportFontAttribute(font, "FACE", format.fontFamily);
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.fontSize != format.fontSize)
+				font = exportFontAttribute(font, "SIZE", format.fontSize);
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.color != format.color)
+			{
+				var rgb:String = format.color.toString(16);
+				while (rgb.length < 6) 
+					rgb = "0" + rgb; // pad with leading zeros
+				rgb = "#" + rgb
+				font = exportFontAttribute(font, "COLOR", rgb);
+			}
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.trackingRight != format.trackingRight)
+				font = exportFontAttribute(font, "LETTERSPACING", format.trackingRight); 
+			if (!ifDifferentFromFormat || ifDifferentFromFormat.kerning != format.kerning)
+				font = exportFontAttribute(font, "KERNING", format.kerning == Kerning.OFF ? "0" : "1");
+						
+			return font;				
+		}
+			
+		/** Exports the flow element by finding the appropriate exporter
+		 * @param flowElement	Element to export
+		 * @return Object	XML/XMLList for the flowElement
+		 */
+		private function exportElement(flowElement:FlowElement):Object
+		{
+			var className:String = flash.utils.getQualifiedClassName(flowElement);
+			var info:FlowElementInfo = _config.lookupByClass(className);
+			if (info != null)
+				return info.exporter(_config.lookupName(className), flowElement);
+			return null;
+		}
+		
+		/** Exports the children of a flow group element
+		 * @param xml XML to append children to
+		 * @param flowGroupElement	the flow group element
+		 */
+		private function exportChildren(xml:XML, flowGroupElement:FlowGroupElement):void
+		{
+			for(var i:int=0; i < flowGroupElement.numChildren; ++i)
+			{
+				xml.appendChild(exportElement(flowGroupElement.getChildAt(i)));	
+			}
+		}
+		
+		/** Helper to establish a parent-child relationship between two xml elements
+		 * and return the parent
+		 * @param parent the intended parent
+		 * @param children the intended children (XML or XMLList)
+		 * @return the parent
+		 */
+		private function nest (parent:XML, children:Object):XML
+		{
+			parent.setChildren(children);
+			return parent;
+		}
+		
+ 	}
+}
\ No newline at end of file
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/HtmlImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/HtmlImporter.as
new file mode 100755
index 0000000..bbd00d9
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/HtmlImporter.as
@@ -0,0 +1,1151 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion 
+{
+	import flash.text.engine.Kerning;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.BreakElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.LeadingModel;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.property.StringProperty;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** 
+	 * @private
+	 * HtmlImporter converts from HTML to TextLayout data structures
+	 */ 	
+	internal class HtmlImporter extends BaseTextLayoutImporter
+	{
+		// TLF formats to which <font/> attributes map directly
+		static internal var _fontDescription:Object = {
+			color:TextLayoutFormat.colorProperty,
+			trackingRight:TextLayoutFormat.trackingRightProperty,
+			fontFamily:TextLayoutFormat.fontFamilyProperty
+		};
+		
+		// <font/> attributes that require custom logic for mapping to TLF formats
+		static internal const _fontMiscDescription:Object = {
+			size	: new StringProperty("size", null, false, null),
+			kerning	: new StringProperty("kerning", null, false, null)
+		};
+				
+		// TLF formats to which <textformat/> attributes map directly		
+		static internal var _textFormatDescription:Object = {
+			paragraphStartIndent:TextLayoutFormat.paragraphStartIndentProperty,
+			paragraphEndIndent:TextLayoutFormat.paragraphEndIndentProperty,
+			textIndent:TextLayoutFormat.textIndentProperty,
+			lineHeight:TextLayoutFormat.lineHeightProperty,
+			tabStops:TextLayoutFormat.tabStopsProperty
+		};	
+		
+		// <textformat/> attributes that require custom logic for mapping to TLF formats
+		static internal const _textFormatMiscDescription:Object = {
+			blockIndent	: new StringProperty("blockIndent", null, false, null)
+		};
+		
+		static internal var _paragraphFormatDescription:Object = {
+			textAlign:TextLayoutFormat.textAlignProperty
+		};
+		
+		static internal const _linkHrefDescription:Object = {
+			href	: new StringProperty("href",   null, false, null)
+		};
+		
+		static internal const _linkTargetDescription:Object = {
+			target	: new StringProperty("target", null, false, null)
+		};
+		
+		static internal const _imageDescription:Object = {
+			height	: InlineGraphicElement.heightPropertyDefinition,
+			width	: InlineGraphicElement.widthPropertyDefinition,
+			src		: new StringProperty("src", null, false, null)};
+		
+		// Separate description because id value is case-sensitive unlike others
+		static internal const _imageMiscDescription:Object = {
+			id		: new StringProperty("id", null, false, null)};
+			
+		static internal const _classDescription:Object =
+		{
+			// A property named 'class' confuses the compiler. 
+			// class	: new StringProperty("class",   null, false, null)
+			// So, we initialize _classDescription in the constructor 
+		};
+		
+		// For some reason, the following can't be initialized here
+		static private var _fontImporter:FontImporter;
+		static private var _fontMiscImporter:CaseInsensitiveTLFFormatImporter;
+		static private var _textFormatImporter:TextFormatImporter;
+		static private var _textFormatMiscImporter:CaseInsensitiveTLFFormatImporter;		
+		static private var _paragraphFormatImporter:HtmlCustomParaFormatImporter;
+		static private var _linkHrefImporter:CaseInsensitiveTLFFormatImporter;
+		static private var _linkTargetImporter:CaseInsensitiveTLFFormatImporter;
+		static private var _ilgFormatImporter:CaseInsensitiveTLFFormatImporter;
+		static private var _ilgMiscFormatImporter:CaseInsensitiveTLFFormatImporter;
+		static private var _classImporter:CaseInsensitiveTLFFormatImporter;
+		
+		// Formats specified by formatting elements in the ancestry of the element being parsed currently 
+		static private var _activeFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(); // to be applied to all flow elements
+		static private var _activeParaFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(); // to be applied to paras only
+		static private var _activeImpliedParaFormat:TextLayoutFormatValueHolder = null;
+		
+		// The basis for relative font size calculation
+		static private var _baseFontSize:Number; 
+		
+		/** Constructor */
+		public function HtmlImporter(textFlowConfiguration:IConfiguration)
+		{
+			super(textFlowConfiguration, null, createConfig());
+		}
+		
+		private static function createConfig():ImportExportConfiguration
+		{
+			var config:ImportExportConfiguration = new ImportExportConfiguration();
+			
+			// inherited	
+			config.addIEInfo("br", BreakElement, BaseTextLayoutImporter.parseBreak, null, false); 
+ 			
+ 			config.addIEInfo("p", ParagraphElement, HtmlImporter.parsePara, null, true);
+ 			config.addIEInfo("span", SpanElement, HtmlImporter.parseSpan, null, false);
+ 			config.addIEInfo("a", LinkElement, HtmlImporter.parseLink, null, false);
+			config.addIEInfo("img", InlineGraphicElement, HtmlImporter.parseInlineGraphic, null, false);
+		
+			// formatting elements
+			config.addIEInfo("font", null, HtmlImporter.parseFont, null, false);
+			config.addIEInfo("textformat", null, HtmlImporter.parseTextFormat, null, false);
+			config.addIEInfo("u", null, HtmlImporter.parseUnderline, null, false);
+			config.addIEInfo("i", null, HtmlImporter.parseItalic, null, false);
+			config.addIEInfo("b", null, HtmlImporter.parseBold, null, false);
+			
+			// create these here - can't be done above
+			if (_classDescription["class"] === undefined)
+			{
+				_classDescription["class"] = new StringProperty("class", null, false, null);
+				_paragraphFormatImporter = new HtmlCustomParaFormatImporter(TextLayoutFormat, _paragraphFormatDescription);
+				_textFormatImporter = new TextFormatImporter(TextLayoutFormat, _textFormatDescription);
+				_fontImporter = new FontImporter(TextLayoutFormat, _fontDescription);
+				_fontMiscImporter = new CaseInsensitiveTLFFormatImporter(Dictionary, _fontMiscDescription);		
+				_textFormatMiscImporter = new CaseInsensitiveTLFFormatImporter(Dictionary, _textFormatMiscDescription);
+				_linkHrefImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_linkHrefDescription,false);
+				_linkTargetImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_linkTargetDescription);
+				_ilgFormatImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_imageDescription);
+				_ilgMiscFormatImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_imageMiscDescription, false);
+				_classImporter = new CaseInsensitiveTLFFormatImporter(Dictionary,_classDescription);
+			}
+			return config;
+		}
+		
+		
+		/** Parse and convert input data
+		 * 
+		 * @param source - the HTML string
+		 */
+		protected override function importFromString(source:String):TextFlow
+		{	
+			// Use toXML rather than the XML constructor because the latter expects
+			// well-formed XML, which source may not be 
+			var xml:XML = toXML(source);
+			return xml ? importFromXML(xml) : null;
+		}
+
+		/** Parse and convert input XML data
+		 */
+		protected override function importFromXML(xmlSource:XML):TextFlow
+		{
+			var textFlow:TextFlow = new TextFlow(_textFlowConfiguration);
+			
+			// Use font size specified in _textFlowConfiguration.textFlowInitialFormat as the base font size
+			// If not specified, use 12
+			_baseFontSize = textFlow.fontSize === undefined ? 12 : textFlow.fontSize;
+			
+			// Unlike other markup formats, the HTML format for TLF does not have a fixed root XML element.
+			// <html> and <body> are optional, and flow elements may or may not be encapsulated in formatting 
+			// elements like <i> or <textformat>. Use parseObject to handle any (expected) root element.
+			parseObject(xmlSource.name().localName, xmlSource, textFlow);
+			
+			// If the last para is implied, there is nothing following it that'll trigger a reset. 
+			// For most importers, this is fine (clear will eventually reset it), but the HTML importer has 
+			// some special behavior associated with the reset (replacing BreakElements with para splits).
+			// Explicitly do so now (must happen before normalization)
+			resetImpliedPara();
+			
+			CONFIG::debug { textFlow.debugCheckNormalizeAll() ; }
+			textFlow.normalize();
+			textFlow.applyWhiteSpaceCollapse();
+			
+			return textFlow;
+		}		
+
+		protected override function clear():void
+		{
+			// Reset active formats and base font size
+			_activeParaFormat.coreStyles = null;
+			_activeFormat.coreStyles = null;
+			super.clear();
+		}
+		
+		tlf_internal override function createImpliedParagraph():ParagraphElement
+		{
+			var rslt:ParagraphElement;
+			var savedActiveFormat:TextLayoutFormatValueHolder = _activeFormat;
+			if (_activeImpliedParaFormat)
+				_activeFormat = _activeImpliedParaFormat;
+			try
+			{
+				rslt = super.createImpliedParagraph();
+			}
+			finally
+			{
+				_activeFormat = savedActiveFormat;
+			}
+			return rslt;
+		}
+
+		public override function createParagraphFromXML(xmlToParse:XML):ParagraphElement
+		{
+			var paraElem:ParagraphElement = new ParagraphElement();
+				
+			// Parse xml attributes for paragraph format
+			var formatImporters:Array = [_paragraphFormatImporter, _classImporter];
+			parseAttributes(xmlToParse, formatImporters);
+			var paragraphFormat:TextLayoutFormat = new TextLayoutFormat(_paragraphFormatImporter.result as ITextLayoutFormat);
+			
+			// Apply paragraph format inherited from formatting elements
+			if (_activeParaFormat)
+				paragraphFormat.apply(_activeParaFormat);
+			if (_activeFormat)
+				paragraphFormat.apply(_activeFormat);
+			
+			// A <FONT/> that is the only child of a <P/> specifies formats that apply to the paragraph itself
+			// Otherwise (i.e., if it has siblings), the formats apply to the elements nested within the <FONT/>
+			// Check for the former case here
+			var fontFormattingElement:XML = getSingleFontChild (xmlToParse);
+			if (fontFormattingElement)
+				paragraphFormat.apply(parseFontAttributes(fontFormattingElement));
+				
+			if (paragraphFormat.lineHeight !== undefined)
+				paragraphFormat.leadingModel = LeadingModel.APPROXIMATE_TEXT_FIELD;
+			
+			paraElem.format = paragraphFormat;
+			
+			// Use the value of the 'class' attribute (if present) as styleName
+			paraElem.styleName =  _classImporter.getFormatValue("class"); 
+					
+			return paraElem;
+		}
+				
+		/** Parse the supplied XML into a paragraph. Parse the <p/> element and its children.
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parsePara(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var paraElem:ParagraphElement = (importFilter as HtmlImporter).createParagraphFromXML(xmlToParse);
+			
+			if (importFilter.addChild(parent, paraElem))
+			{
+				// Parse children, but if there is only one child, a <FONT/>, skip to *its* children.
+				// That's because the single <FONT/> chuld has already been parsed in createParagraphFromXML.
+				var fontFormattingElement:XML = getSingleFontChild (xmlToParse);
+				parseChildrenUnderNewActiveFormat (importFilter, fontFormattingElement ? fontFormattingElement : xmlToParse, paraElem, _activeFormat, null);
+				
+				//if parsing an empty paragraph, create a Span for it.
+				if (paraElem.numChildren == 0)
+					paraElem.addChild(new SpanElement());
+			}
+			
+			// Replace break elements with paragraph splits
+			// This must happen before normalization else BreakElements may merge or become spans
+			replaceBreakElementsWithParaSplits(paraElem);
+		}
+		
+		protected override function onResetImpliedPara(para:ParagraphElement):void
+		{
+			// Replacing break elements with paragraph splits, even for implied paras
+			replaceBreakElementsWithParaSplits (para);
+		}
+		
+		/** If the provided xml has a single child <FONT.../>, get it
+		 */
+		static private function getSingleFontChild (xmlToParse:XML):XML
+		{
+			var children:XMLList = xmlToParse.children();
+			if (children.length() == 1)
+			{
+				var child:XML = children[0];
+				if (child.name().localName.toLowerCase() == "font")
+					return child;
+			}
+			
+			return null;
+		}
+			
+		private function createLinkFromXML(xmlToParse:XML):LinkElement
+		{
+			var linkElem:LinkElement = new LinkElement();
+
+			var formatImporters:Array = [ _linkHrefImporter, _linkTargetImporter ];
+			parseAttributes(xmlToParse, formatImporters);
+			
+			linkElem.href = _linkHrefImporter.getFormatValue("href");
+			linkElem.target = _linkTargetImporter.getFormatValue("target");
+			
+			// Handle difference in defaults between TextField and TLF 
+			// target "_self" vs. null (equivalent to "_blank")
+			if (!linkElem.target)
+				linkElem.target = "_self";
+				
+			//  Apply active format
+			linkElem.format = _activeFormat;
+
+			return linkElem;
+		}
+		
+		/** Parse the supplied XML into a LinkElement. Parse the <a/> element and its children.
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseLink(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var linkElem:LinkElement = HtmlImporter(importFilter).createLinkFromXML(xmlToParse);
+			
+			if (importFilter.addChild(parent, linkElem))
+			{
+				parseChildrenUnderNewActiveFormat (importFilter, xmlToParse, linkElem, _activeFormat, null);
+				
+				// If parsing an empty link, create a Span for it.
+				if (linkElem.numChildren == 0)
+					linkElem.addChild(new SpanElement());
+			}
+		}	
+		
+		/** Static method for constructing a span from XML. Parse the <span> ... </span> tag. 
+		 * Insert the new content into its parent
+		 * Note: Differs from BaseTextLayoutImporter.parseSpan in that it allows nested <span/> elements. 
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseSpan(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var firstSpan:SpanElement = new SpanElement();
+			
+			// Use the value of the 'class' attribute (if present) as styleName
+			var formatImporters:Array = [_classImporter];
+			importFilter.parseAttributes(xmlToParse,formatImporters);
+			firstSpan.styleName = _classImporter.getFormatValue("class");
+			
+			// Apply active format
+			firstSpan.format = _activeFormat;
+			
+			var elemList:XMLList = xmlToParse[0].children();
+			if(elemList.length() == 0)
+			{
+				// Empty span, but may have formatting, so don't strip it out. 
+				// Note: the normalizer may yet strip it out if it is not the last child, but that's the normalizer's business.
+				importFilter.addChild(parent, firstSpan); 
+				return;
+			}
+	
+			for each (var child:XML in elemList) 
+			{
+				var elemName:String = child.name() ? child.name().localName : null;
+					
+				if (elemName == null) // span text
+				{
+					if (firstSpan.parent == null)	// hasn't been used yet
+					{
+						firstSpan.text = child.toString();
+						importFilter.addChild(parent, firstSpan);
+					}
+					else
+					{
+						var s:SpanElement = new SpanElement();
+						copyAllStyleProps(s,firstSpan);
+						s.text = child.toString();
+						importFilter.addChild(parent, s);
+					}
+				}
+				else 
+				{
+					// Anything else: will become siblings of the spans that are (or will be) created for text nodes
+					// (assuming that's valid). For example <span class="A">A quick <span class="B">fox</span></span>
+					// is treated like <span class="A">A quick </span><span class="B">fox</span>. Consequently, any formatting
+					// associated with class "A" will not apply to "fox". This is a shortcoming in the TLF object model: 
+					// SpanElements can't nest.
+					importFilter.parseObject(elemName, child, parent);
+				}
+			}
+		} 
+	
+		private function createInlineGraphicFromXML(xmlToParse:XML):InlineGraphicElement
+		{				
+			var imgElem:InlineGraphicElement = new InlineGraphicElement();
+
+			var formatImporters:Array = [_ilgFormatImporter, _ilgMiscFormatImporter];	
+			parseAttributes(xmlToParse,formatImporters);
+			
+			var source:String = _ilgFormatImporter.getFormatValue("src");
+			imgElem.source = source;
+				
+			// if not defined then let InlineGraphic set its own default
+			imgElem.height = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.height,_ilgFormatImporter.getFormatValue("height"));
+			imgElem.width  = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.width,_ilgFormatImporter.getFormatValue("width"));
+				
+			/* Not currently supported
+			var floatVal:String = _ilgFormatImporter.getFormatValue("align");
+			// Handle difference in defaults between TextField and TLF 
+			// float "left" vs. "none"
+			imgElem.float = floatVal ? floatVal : Float.LEFT;
+			*/
+			
+			var id:String = _ilgMiscFormatImporter.getFormatValue("id");
+			imgElem.id = id;
+			
+			//  Apply active format
+			imgElem.format = _activeFormat;
+			
+			return imgElem;
+		}
+
+		/** Parse the supplied XML into an InlineGraphicElement. Parse the <img/> element.
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the new content
+		 */
+		static public function parseInlineGraphic(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var ilg:InlineGraphicElement = HtmlImporter(importFilter).createInlineGraphicFromXML(xmlToParse);
+			importFilter.addChild(parent, ilg);
+		}
+		
+		public override function createTabFromXML(xmlToParse:XML):TabElement
+		{
+			return null; // no tabs in HTML
+		}
+			
+		/** Parse the attributes of the <Font/> formatting element and returns the corresponding TLF format
+		 */
+		private function parseFontAttributes(xmlToParse:XML):ITextLayoutFormat
+		{
+			var formatImporters:Array = [_fontImporter, _fontMiscImporter];
+			parseAttributes(xmlToParse, formatImporters);
+			
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(_fontImporter.result as ITextLayoutFormat);
+			
+			var kerning:String = _fontMiscImporter.getFormatValue("kerning");
+			if (kerning)
+			{
+				var kerningVal:Number = Number(kerning);
+				newFormat.kerning = kerningVal == 0 ? Kerning.OFF : Kerning.AUTO;
+			}
+			
+			var size:String = _fontMiscImporter.getFormatValue("size");
+			if (size)
+			{
+				var sizeVal:Number = TextLayoutFormat.fontSizeProperty.setHelper(NaN, size);
+				if (!isNaN(sizeVal))
+				{
+					if (size.search(/\s*(-|\+)/) != -1) // leading whitespace followed by + or -
+						sizeVal += _baseFontSize;		// implies relative font sizes
+					newFormat.fontSize = sizeVal;
+				}
+			}
+			
+			return newFormat;
+		}
+		
+		/** Parse the <Font/> formatting element
+		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
+		 */
+		static public function parseFont(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var newFormat:ITextLayoutFormat = (importFilter as HtmlImporter).parseFontAttributes (xmlToParse);
+			parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importFilter, xmlToParse, parent, newFormat);
+		}
+		
+		/** Parse the <TextFormat> formatting element
+		 * Calculates the new format to apply to _activeParaFormat and continues parsing down the hierarchy
+		 */
+		static public function parseTextFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{	
+			var formatImporters:Array = [_textFormatImporter, _textFormatMiscImporter];
+			importFilter.parseAttributes(xmlToParse, formatImporters);
+			
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(_textFormatImporter.result as ITextLayoutFormat);
+			
+			var blockIndent:String = _textFormatMiscImporter.getFormatValue("blockIndent");
+			if (blockIndent)
+			{
+				// TODO: Nested <TextFormat/>?
+				var blockIndentVal:Number = TextLayoutFormat.paragraphStartIndentProperty.setHelper(NaN, blockIndent);
+				if (!isNaN(blockIndentVal))
+					newFormat.paragraphStartIndent = newFormat.paragraphStartIndent === undefined ? blockIndentVal : newFormat.paragraphStartIndent + blockIndentVal;
+			}
+
+			parseChildrenUnderNewActiveFormat (importFilter, xmlToParse, parent, _activeParaFormat, newFormat, true);
+		}
+		
+		/** Parse the <b> formatting element
+		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
+		 */
+		static public function parseBold(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{	
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+			newFormat.fontWeight = flash.text.engine.FontWeight.BOLD;
+			
+			parseChildrenUnderNewActiveFormatWithImpliedParaFormat (importFilter, xmlToParse, parent, newFormat);
+		}
+		
+		/** Parse the <i> formatting element
+		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
+		 */
+		static public function parseItalic(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{	
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+			newFormat.fontStyle = flash.text.engine.FontPosture.ITALIC;
+			parseChildrenUnderNewActiveFormatWithImpliedParaFormat (importFilter, xmlToParse, parent, newFormat);
+		}
+		
+		/** Parse the <u> formatting element
+		 * Calculates the new format to apply to _activeFormat and continues parsing down the hierarchy
+		 */
+		static public function parseUnderline(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{	
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+			newFormat.textDecoration = flashx.textLayout.formats.TextDecoration.UNDERLINE;
+			parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importFilter, xmlToParse, parent, newFormat);
+
+		}
+		
+		static private function parseChildrenUnderNewActiveFormatWithImpliedParaFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement, newFormat:ITextLayoutFormat):void
+		{
+			var oldActiveImpliedParaFormat:TextLayoutFormatValueHolder = _activeImpliedParaFormat;
+			if (_activeImpliedParaFormat == null)
+				_activeImpliedParaFormat = new TextLayoutFormatValueHolder(_activeFormat);
+			try
+			{
+				parseChildrenUnderNewActiveFormat(importFilter, xmlToParse, parent, _activeFormat, newFormat, true);
+			}
+			finally
+			{
+				_activeImpliedParaFormat = oldActiveImpliedParaFormat;
+			}
+		}
+		
+		/** Updates the current active format and base font size as specified, parses children, and restores the active format and base font size
+		 * There are two different use cases for this method:
+		 * - Parsing children of a formatting XML element like <Font/> or <TextFormat/>. In this case, the TLF format corresponding to the formatting element
+		 * (newFormat) is applied to the currently active format (_activeFormat in the case of <Font/> and _activeParaFormat in the case of <TextFormat/>). 
+		 * Children of the formatting element are parsed under this new active format.
+		 * - Parsing children of a flow XML element like <P/> or <A/>. In this case, newFormat is null and the currently active format (_activeFormat) is reset.
+		 * Children of the flow element are parsed under this newly reset format. This is to avoid redundancy (the format is already applied to the flow element). 
+		 * 
+		 * @param importFilter	parser object
+		 * @param xmlToParse	content to parse
+		 * @param parent 		the parent for the parsed children
+		 * @param currFormat	the active format (_activeFormat or _activeParaFormat)
+		 * @param newFormat		the format to apply to currFormat while the children are being parsed. If null, currFormat is to be reset.
+		 * @param chainedParent whether parent actually corresponds to xmlToParse or has been chained (such as when xmlToParse is a formatting element). See BaseTextLayoutImporter.parseFlowGroupElementChildren
+		 */
+		static private function parseChildrenUnderNewActiveFormat (importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement, currFormat:TextLayoutFormatValueHolder, newFormat:ITextLayoutFormat, chainedParent:Boolean=false):void
+		{
+			// Remember the current state
+			var restoreBaseFontSize:Number = _baseFontSize;
+			var restoreCoreStyles:Object = Property.shallowCopy(currFormat.coreStyles);
+			
+			if (newFormat)
+			{
+				// Update base font size based on the new format
+				if (newFormat.fontSize !== undefined)
+					_baseFontSize = newFormat.fontSize; 
+					
+				// Apply the new format
+				currFormat.apply(newFormat);
+			}
+			else
+			{
+				// Base font size remains unchanged
+				
+				// Reset the new format
+				currFormat.coreStyles = null;
+			}
+			
+			try
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, parent, null, chainedParent);
+			}
+			finally
+			{
+				// Restore 
+				currFormat.coreStyles = restoreCoreStyles;
+				_baseFontSize = restoreBaseFontSize;
+			}
+		}
+		
+		protected override function handleUnknownAttribute(elementName:String, propertyName:String):void
+		{
+			// A toss-up: report error or ignore? Ignore for now
+			// If we do end up reporting error, we should add exceptions for documented attributes that we don't handle
+			// like align on <img/>
+		}
+		
+		protected override function handleUnknownElement(name:String, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			// Not an error (it may be a styling element like <h1/>); continue parsing children
+			parseFlowGroupElementChildren (xmlToParse, parent, null, true);
+		}										
+		
+		tlf_internal override function  parseObject(name:String, xmlToParse:XML, parent:FlowGroupElement, exceptionElements:Object=null):void
+		{
+			// override to allow upper case tag names
+			super.parseObject(name.toLowerCase(), xmlToParse, parent, exceptionElements);
+		}
+		
+		protected override function checkNamespace(xmlToParse:XML):Boolean
+		{	
+			/* Ignore namespace */
+			return true;
+		}
+		
+		/** Splits the paragraph wherever a break element occurs and removes the latter
+		 * This is to replicate TextField handling of <br/>: splits the containing paragraph (implied or otherwise)
+		 * The <br/> itself doesn't survive.
+		 */
+		static private function replaceBreakElementsWithParaSplits(para:ParagraphElement):void
+		{
+			// performance: when splitting the paragraph into multiple paragraphs take it out of the TextFlow
+			var paraArray:Array;
+			var paraIndex:int;
+			var paraParent:FlowGroupElement;
+	
+			// Find each BreakElement and split into a new paragraph
+			var elem:FlowLeafElement = para.getFirstLeaf();
+			while (elem)
+			{
+				if (!(elem is BreakElement))
+				{
+					elem = elem.getNextLeaf(para);
+					continue;					
+				}
+				if (!paraArray)
+				{
+					paraArray = [ para ];
+					paraParent = para.parent;
+					paraIndex = paraParent.getChildIndex(para);
+					paraParent.removeChildAt(paraIndex);
+				}
+					
+				// Split the para right after the BreakElement
+				//CONFIG::debug { assert(elem.textLength == 1,"Bad TextLength in BreakElement"); }
+				CONFIG::debug {assert( para.getAbsoluteStart() == 0,"Bad paragraph in replaceBreakElementsWithParaSplits"); }
+				para = para.splitAtPosition(elem.getAbsoluteStart()+elem.textLength) as ParagraphElement;
+				paraArray.push(para);
+					
+				// Remove the BreakElement
+				elem.parent.removeChild(elem);	
+				
+				// point elem to the first leaf of the new paragraph
+				elem = para.getFirstLeaf();
+			}
+			
+			if (paraArray)
+				paraParent.replaceChildren(paraIndex,paraIndex,paraArray);
+		}
+		
+		/** HTML parsing code
+		 *  Uses regular expressions for recognizing constructs like comments, tags etc.
+		 *  and a hand-coded parser to recognize the document structure and covert to well-formed xml
+		 *  TODO-1/16/2009:List caveats
+		 */ 
+		
+		/** Regex for stuff to be stripped: a comment, processing instruction, or a declaration
+		 *
+		 * <!--.*?--> - comment
+		 *   <!-- - start comment
+		 *   .*? - anything (including newline character, thanks to the s flag); the ? prevents a greedy match (which could match a --> later in the string) 
+		 *  --> - end comment
+		 *  
+		 * <\?(".*?"|'.*?'|[^>]+)*> - processing instruction
+		 *   <\? - start processing instruction
+		 *   (".*?"|'.*?'|[^>]+)* - 0 or more of the following (interleaved in any order)
+		 *     ".*?" - anything (including >) so long as it is within double quotes; the ? prevents a greedy match (which could match everything until a later " in the string) 
+		 *     '.*?' - anything (including >) so long as it is within single quotes; the ? prevents a greedy match (which could match everything until a later ' in the string)
+		 *     [^>"']+ - one or more characters other than > (because > ends the processing instruction), " (handled above), ' (handled above) 
+		 *   > - end processing instruction
+		 *
+		 * <!(".*?"|'.*?'|[^>"']+)*> - declaration; 
+		 * TODO-1/15/2009:not sure if a declaration can contain > within quotes. Assuming it can, the regex is  
+		 *  is exactly like processing instruction above except it uses a ! instead of a ?
+		 */
+		private static var stripRegex:RegExp = /<!--.*?-->|<\?(".*?"|'.*?'|[^>"']+)*>|<!(".*?"|'.*?'|[^>"']+)*>/sg;
+						
+		/** Regular expression for an HTML tag
+		 * < - open
+		 *
+		 * (\/?) - start modifier; 0 or 1 occurance of one of /
+		 *
+		 * (\w+) - tag name; 1 or more name characters
+		 *
+		 * ((?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?)*) - attributes; 0 or more of the following
+		 *   (?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?) - attribute; 1 or more space, followed by 1 or more name characters optionally followed by
+		 *      \s*=\s*(?:".*?"|'.*?'|[\w\.]+) - attribute value assignment; optional space followed by = followed by more optional space followed by one of
+		 *         ".*?" - quoted attribute value (using double quotes); the ? prevents a greedy match (which could match everything until a later " in the string)
+		 *         '.*?' - quoted attribute value (using single quotes); the ? prevents a greedy match ((which could match everything until a later ' in the string)
+		 *         [\w\.]+ - unquoted attribute value; can only contain name characters or a period
+		 *  Note: ?: specifies a non-capturing group (i.e., match won't be recorded or used as a numbered back-reference)
+		 *
+		 * \s* - optional space
+		 *
+		 * (\/?) - end modifer (0 or 1 occurance of /)
+		 *
+		 * > - close*/
+		private static var tagRegex:RegExp = /<(\/?)(\w+)((?:\s+\w+(?:\s*=\s*(?:".*?"|'.*?'|[\w\.]+))?)*)\s*(\/?)>/sg;
+		
+		/** Regular expression for an attribute. Except for grouping differences, this regex is the same as the one that appears in tagRegex
+		 */
+		private static var attrRegex:RegExp = /\s+(\w+)(?:\s*=\s*(".*?"|'.*?'|[\w\.]+))?/sg;
+		
+		/** Wrapper for core HTML parsing code that manages XML settings during the process
+		 */
+		private function toXML(source:String):XML
+		{
+			var xml:XML;
+			
+			var originalSettings:Object = XML.settings();
+			try
+			{
+				XML.ignoreProcessingInstructions = false;		
+				XML.ignoreWhitespace = false;	
+
+				xml = toXMLInternal(source);				
+			}			
+			finally
+			{
+				XML.setSettings(originalSettings);
+			}	
+			
+			return xml;
+		}	
+		
+		/** Convert HTML string to well-formed xml, accounting for the following HTML oddities
+		 * 
+		 * 1) Start tags are optional for some elements.
+		 * Optional start tag not specified</html>
+		 * TextField dialect: This is true for all elements. 
+		 * 
+		 * 2) End tags are optional for some elements. Elements with missing end tags may be implicitly closed by
+		 *    a) start-tag for a peer element
+		 *    <p>p element without end tag; closed by next p start tag
+		 *    <p>closes previous p element with missing end tag</p>
+		 * 
+		 *    b) end-tag for an ancestor element 
+		 * 	  <html><p>p element without end tag; closed by next end tag of an ancestor</html>
+		 *     TextField dialect: This is true for all elements. 
+		 * 
+		 * 3) End tags are forbidden for some elements
+		 * <br> and <br/> are valid, but <br></br> is not
+		 * TextField dialect: Does not apply. 
+		 * 
+		 * 4) Element and attribute names may use any case
+		 * <P ALign="left"></p>
+		 * 
+		 * 5) Attribute values may be unquoted
+		 * <p align=left/>
+		 * 
+		 * 6) Boolean attributed may assume a minimized form
+		 * <p selected/> is equivalent to <p selected="selected"/>
+		 * 
+		 */	
+		private function toXMLInternal(source:String):XML
+		{
+			// Strip out comments, processing instructions and declaratins	
+			source = source.replace(stripRegex, "");
+			
+			// Parse the source, looking for tags and interleaved text content, creating an XML hierarchy in the process.
+			// At any given time, there is a chain of 'open' elements corresponding to unclosed tags, the innermost of which is 
+			// tracked by the currElem. Content (element or text) parsed next is added as a child of currElem.
+			
+			// Root of the XML hierarchy (set to <html/> because the html start tag is optional)
+			// Note that source may contain an html start tag, in which case we'll end up with two such elements
+			// This is not quite correct, but handled by the importer  
+			var root:XML = <html/>; 
+			var currElem:XML = root;  
+			
+			var lastIndex:int = tagRegex.lastIndex = 0;
+			var openElemName:String;
+						
+			do
+			{						
+				var result:Object = tagRegex.exec(source);
+				if (!result)
+				{
+					// No more tags: add text (starting at search index) as a child of the innermost open element and break out
+					appendTextChild (currElem, source.substring(lastIndex));
+					break;
+				}
+				
+				if (result.index != lastIndex)
+				{
+					// Add text between tags as a child of the innermost open element
+					appendTextChild (currElem, source.substring(lastIndex, result.index));
+				}
+				
+				var tag:String = result[0]; // entire tag
+				var hasStartModifier:Boolean = (result[1] == "\/"); // modifier after < (/ for end tag)
+				var name:String = result[2].toLowerCase();  // name; use lower case
+				var attrs:String = result[3];  // attributes; including whitespace
+				var hasEndModifier:Boolean = (result[4] == "\/"); // modifier before > (/ for composite start and end tag)
+
+				if (!hasStartModifier) // start tag 
+				{	
+					// Special case for implicit closing of <p>
+					// TODO-12/23/2008: this will need to be handled more generically				
+					if (name == "p" && currElem.name().localName == "p")
+						currElem = currElem.parent();
+						
+					// Create an XML element by constructing a tag that can be fed to the XML constructor. Specifically, ensure
+					// - it is a composite tag (start and end tag together) using the terminating slash shorthand
+					// - element and attribute names are lower case (this is not required, but doesn't hurt)
+					// - attribute values are quoted  	
+					// - boolean attributes are fully specified (e.g., selected="selected" rather than selected)
+					tag = "<" + name;
+					do
+					{
+						var innerResult:Object = attrRegex.exec(attrs);
+						if (!innerResult)
+							break;
+							
+						var attrName:String = innerResult[1].toLowerCase();
+						tag += " " + attrName + "="; 
+						var val:String = innerResult[2] ? innerResult[2] : attrName /* boolean attribute with implied value equal to attribute name */; 
+						var startChar:String = val.charAt(0); 
+						tag += ((startChar == "'" || startChar == "\"") ? val : ("\"" + val + "\""));
+						
+					} while (true);	 
+					tag += "\/>";
+					
+					// Add the corresponding element as a child of the innermost open element 
+					currElem.appendChild(new XML(tag));
+					
+					// The new element becomes the innermost open element unless it is already closed because
+					// - this is a composite start and end tag (i.e., has an end modifier) 
+					// - the start tag itself implies closure
+					if (!hasEndModifier && !doesStartTagCloseElement(name))
+						currElem = currElem.children()[currElem.children().length()-1];	
+				}	
+				else // end tag
+				{	
+					if (hasEndModifier || attrs.length)
+					{
+						reportError(GlobalSettings.resourceStringFunction("malformedTag",[tag]));
+					}
+					else
+					{
+						/*
+						// Does not apply to TextField dialect
+						if (isEndTagForbidden(name))
+						{
+							xxxreportError("End tag is not allowed for element " + name); NOTE : MAKE A LOCALIZABLE ERROR IF THIS COMES BACK
+							return null;
+						}*/
+					
+						// Move up the chain of open elements looking for a matching name
+						// The matching element is closed and its parent becomes the innermost open element
+						// Report error if matching element is not found and it requires a start tag
+						// All intermediate open elements are also closed provided they don't require end tags
+						// Report error if an intermediate element requires end tags
+						var openElem:XML = currElem;
+						do
+						{
+							openElemName = openElem.name().localName; 
+							openElem = openElem.parent();
+							
+							if (openElemName == name)
+							{
+								currElem = openElem;
+								break;
+							}
+							/*
+							// Does not apply to TextField dialect
+							else if (isEndTagRequired(openElemName))
+							{
+								xxxreportError("Missing end tag for element " + openElemName);
+								return null;
+							}*/
+	
+							
+							if (!openElem)
+							{
+								// Does not apply to TextField dialect
+								/*if (isStartTagRequired(name))
+								{
+									xxxreportError("Unexpected end tag " + name);
+									return null;
+								}*/
+								break;
+							}					
+						}
+						while (true);
+					}
+				}
+				
+				lastIndex = tagRegex.lastIndex;
+				if (lastIndex == source.length)
+					break; // string completely parsed
+					
+			} while (currElem); // null currElem means <html/> has been closed, so ignore everything else		
+			
+			// No more string to parse, specifically, no more end tags. 
+			// Validate that remaining open elements do not require end tags.
+			// Does not apply to TextField dialect
+			/* while (currElem)
+			{
+				openElemName = currElem.name().localName; 
+				if (isEndTagRequired(openElemName))
+				{
+					xxxreportError("Missing end tag for element " + openElemName);
+					return null;
+				}
+				currElem = currElem.parent();
+			}*/	
+			
+			return root;
+		}
+		
+		/** TODO-1/16/2009-Evaluate if following code may be better implemented using dictionaries queried at runtime
+		 */
+		/* 
+		// TextField dialect: Not used  
+		private function isStartTagRequired (tagName:String):Boolean
+		{
+			switch (tagName)
+			{
+				case "a":
+				case "b":
+				case "br":
+				case "font":
+				case "i":
+				case "img":
+				case "p":
+				case "span":
+				case "textformat":
+				case "u":
+					return true;
+				default:
+					// html, head, body, and unrecognized elements (which are handled leniently)
+					return false;
+			}
+		}
+		
+		private function isEndTagRequired (tagName:String):Boolean
+		{
+			switch (tagName)
+			{
+				case "a":
+				case "b":
+				case "font":
+				case "i":
+				case "span":
+				case "textformat":
+				case "u":
+					return true;
+				default:
+					// html, head, body, p, br, image and unrecognized elements (which are handled leniently)
+					return false; 	
+			}
+		}
+		
+		private function isEndTagForbidden (tagName:String):Boolean
+		{
+			switch (tagName)
+			{
+				case "br":
+				case "img":
+					return true;
+				default:
+					return false;
+			}
+		}*/
+		
+		private function doesStartTagCloseElement (tagName:String):Boolean
+		{
+			switch (tagName)
+			{
+				case "br":
+				case "img":
+					return true;
+				default:
+					return false;
+			}
+		}
+		
+		private static const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g;	
+
+		/** Adds text as a descendant of the specified XML element. Adds an intermediate <span> element is created if parent is not a <span>
+		 *  No action is taken for whitespace-only text
+		 */
+		private function appendTextChild(parent:XML, text:String):void
+		{
+			// No whitespace collapse
+			// if (text.match(anyPrintChar).length != 0) 
+			{
+				var parentIsSpan:Boolean = (parent.localName() == "span");
+				var elemName:String = parentIsSpan ? "dummy" : "span";
+				
+				//var xml:XML = <{elemName}/>;
+				//xml.appendChild(text);
+				// The commented-out code above doesn't handle character entities like &lt; 
+				// The following lets the XML constructor handle them 
+				var xmlText:String = "<" + elemName + ">" + text + "<\/" + elemName + ">";
+				try
+				{
+					var xml:XML = new XML(xmlText);
+					parent.appendChild(parentIsSpan ? xml.children()[0] : xml);
+				}
+				catch (e:*)
+				{
+					// Report malformed content like "<" instead of "&lt;"
+					reportError(GlobalSettings.resourceStringFunction("malformedMarkup",[text]));
+				}
+					
+			}
+		}	
+	}
+}
+
+import flashx.textLayout.conversion.TLFormatImporter;
+
+/** Specialized to provide case insensitivity (as required by TEXT_FIELD_HTML_FORMAT)
+ *  Keys need to be lower-cased. Values may or may not based on a flag passed to the constructor. 
+ */
+class CaseInsensitiveTLFFormatImporter extends TLFormatImporter
+{
+	public function CaseInsensitiveTLFFormatImporter(classType:Class,description:Object, convertValuesToLowerCase:Boolean=true)
+	{
+		_convertValuesToLowerCase = convertValuesToLowerCase;
+		
+		var lowerCaseDescription:Object = new Object();
+		for (var prop:Object in description)
+		{
+			lowerCaseDescription[prop.toLowerCase()] = description[prop];
+		}
+		
+		super(classType, lowerCaseDescription);
+	}
+	
+	public override function importOneFormat(key:String,val:String):Boolean
+	{
+		return super.importOneFormat(key.toLowerCase(), _convertValuesToLowerCase ? val.toLowerCase() : val);  
+	} 
+	
+	public function getFormatValue (key:String):*
+	{
+		return result ? result[key.toLowerCase()] : undefined;
+	}
+	
+	private var _convertValuesToLowerCase:Boolean;
+}
+
+class HtmlCustomParaFormatImporter extends TLFormatImporter
+{
+	public function HtmlCustomParaFormatImporter(classType:Class,description:Object)
+	{
+		super(classType,description);
+	}
+	
+	public override function importOneFormat(key:String,val:String):Boolean
+	{
+		key = key.toLowerCase();
+		
+		if (key == "align")
+			key = "textAlign";
+		return super.importOneFormat(key,val.toLowerCase()); // covert val to lowercase because TLF won't accept, say, "RIGHT"
+	} 
+}
+
+class TextFormatImporter extends TLFormatImporter
+{
+	public function TextFormatImporter(classType:Class,description:Object)
+	{
+		super(classType,description);
+	}
+	
+	public override function importOneFormat(key:String,val:String):Boolean
+	{
+		key = key.toLowerCase();
+		
+		if (key == "leftmargin")
+			key = "paragraphStartIndent"; // assumed to be left-to-right text since we don't handle DIR attribute
+		else if (key == "rightmargin")
+			key = "paragraphEndIndent";   // assumed to be left-to-right text since we don't handle DIR attribute
+		else if (key == "indent")
+			key = "textIndent";
+		else if (key == "leading")
+			key = "lineHeight";
+		else if (key == "tabstops")
+		{
+			key = "tabStops";
+			// Comma-delimited in TextField HTML format, space delimited in TLF
+			val = val.replace(/,/g, ' '); 
+		}
+		return super.importOneFormat(key,val); // no case-coversion required, values for these formats in TLF are case-insensitive
+	} 
+}
+
+class FontImporter extends TLFormatImporter
+{
+	public function FontImporter(classType:Class,description:Object)
+	{
+		super(classType,description);
+	}
+	
+	public override function importOneFormat(key:String,val:String):Boolean
+	{
+		key = key.toLowerCase();
+		if (key == "letterspacing")
+			key = "trackingRight";
+		else if (key == "face")
+			key = "fontFamily";
+		return super.importOneFormat(key,val);  // no case-coversion required, values for these formats in TLF are case-insensitive
+	} 
+}
+
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/IFormatImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/IFormatImporter.as
new file mode 100755
index 0000000..c034126
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/IFormatImporter.as
@@ -0,0 +1,31 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.elements.TextFlow;
+	
+	[ExcludeClass]
+	/** Interface for exporting text content from a TextFlow to either a String or XML. */
+	public interface IFormatImporter
+	{	
+		function reset():void;
+		function get result():Object;
+		function importOneFormat(key:String,val:String):Boolean
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/ITextExporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/ITextExporter.as
new file mode 100755
index 0000000..7f17699
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/ITextExporter.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.elements.TextFlow;
+	
+	/** 
+	 * Interface for exporting text content from a 
+	 * TextFlow instance to either String or XML format. 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public interface ITextExporter
+	{	
+		/** 
+		 * Export text content from a TextFlow instance in String or XML format.
+		 * <p>Set the <code>conversionType</code> parameter to either of the following values:
+		 * <ul>
+		 *   <li><code>flashx.textLayout.conversion.ConversionType.STRING_TYPE</code>;</li>
+		 *   <li><code>flashx.textLayout.conversion.ConversionType.XML_TYPE</code>.</li>
+		 * </ul>
+		 * </p>
+		 * @param source	The TextFlow to export
+		 * @param conversionType 	Return a String (STRING_TYPE) or XML (XML_TYPE).
+		 * @return Object	The exported content
+		 * @includeExample examples\ITextExporterExample.as -noswf
+		 * @see flashx.textLayout.conversion.ConversionType
+	 	 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function export(source:TextFlow, conversionType:String):Object;
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/ITextImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/ITextImporter.as
new file mode 100755
index 0000000..22c74e3
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/ITextImporter.as
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.elements.TextFlow;
+	
+	/** 
+	 * Interface for importing text content into a TextFlow from an external source. 
+	 * @includeExample examples\ITextImporterExample.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface ITextImporter
+	{	
+		/** 
+		 * Import text content from an external source and convert it into a TextFlow.
+		 * @param source		Data to convert
+		 * @return TextFlow created from the source.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function importToFlow(source:Object):TextFlow;
+
+		/** 
+		 * Errors encountered while parsing. This will be empty if there were no errors.
+		 * Value is a vector of Strings.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get errors():Vector.<String>;
+		
+		/** 
+		 * Parsing errors during import will cause exceptions if throwOnError is <code>true</code>. 
+	 	 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get throwOnError():Boolean;
+		function set throwOnError(value:Boolean):void;
+	}
+}
\ No newline at end of file
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/ImportExportConfiguration.as b/textLayout_conversion/src/flashx/textLayout/conversion/ImportExportConfiguration.as
new file mode 100755
index 0000000..a4bb2cd
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/ImportExportConfiguration.as
@@ -0,0 +1,122 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.BreakElement;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.elements.DivElement;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TextFlow;
+
+	/** Configure for import/export of standard components.
+	 * Configures the import/export package so it can export all the standard FlowElements. 
+	 * @see flashx.textLayout.elements.Configuration
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	internal class ImportExportConfiguration 
+	{
+		/** array of FlowElementInfo objects (key = name, value = FlowElementInfo) */	
+		private var flowElementInfoList:Object;	
+
+		/** Constructor.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		 */
+		public function ImportExportConfiguration()
+		{
+		}
+		
+		/** Add a parser for a new FlowElement type. This allows FlowElements to be added from outside the main system,
+		 * and still have the main system be able to import them from XML.
+		 * @param name		the name of the FlowElement class, as it appear in the XML
+		 * @param flowClass	the class of the FlowElement
+		 * @param parser	a function capable of parsing the XML into the flow element
+		 * @param	isParagraphFormattedElement Boolean indicating if this class is a subclass of ParagraphFormattedElement
+		 * @private - this should really be tf_internal
+		 */
+		public function addIEInfo(name:String, flowClass:Class, parser:Function, exporter:Function, isParagraphFormattedElement:Boolean):void
+		{
+			if (flowElementInfoList == null)
+				flowElementInfoList = new Object();
+			CONFIG::debug { assert (lookup(name) == null, "FlowElementInfo already exists");}
+			flowElementInfoList[name] = new FlowElementInfo(flowClass, parser, exporter, isParagraphFormattedElement);
+		}
+		
+		/** @private */
+		public function overrideIEInfo(name:String, flowClass:Class, parser:Function, exporter:Function):void
+		{
+			if (flowElementInfoList == null)
+				flowElementInfoList = new Object();
+			
+			CONFIG::debug { assert (lookup(name) != null, "FlowElementInfo doesn't already exist");}
+			flowElementInfoList[name].flowClass = flowClass;
+			flowElementInfoList[name].parser = parser;
+			flowElementInfoList[name].exporter = exporter;
+		}
+		
+		/** Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * @param name				the name of the FlowElement class, as it appears in the XML
+		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
+		 * @private
+		 */
+		public function lookup(name:String):FlowElementInfo
+		{
+			return flowElementInfoList ? flowElementInfoList[name] : null;
+		}
+
+		/** Return the element name for the class
+		 * @param classToMatch		fully qualified class name of the FlowElement
+		 * @return name				export name to use for class
+		 * @private
+		 */
+		public function lookupName(classToMatch:String):String
+		{
+			for (var name:String in flowElementInfoList)
+			{
+				if (flowElementInfoList[name].flowClassName == classToMatch)
+					return name;
+			}
+			return null;
+		}
+
+		/** Return the information being held about the FlowElement, as a FlowElementInfo.
+		 * @param classToMatch		fully qualified class name of the FlowElement
+		 * @return FlowElementInfo	the information being held, as it was supplied to addParseInfo
+		 * @private
+		 */
+		public function lookupByClass(classToMatch:String):FlowElementInfo
+		{
+			for (var name:String in flowElementInfoList)
+			{
+				if (flowElementInfoList[name].flowClassName == classToMatch)
+					return flowElementInfoList[name];
+			}
+			return null;
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextExporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextExporter.as
new file mode 100755
index 0000000..51183f9
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextExporter.as
@@ -0,0 +1,158 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.elements.*;
+
+	/** 
+	 * Export filter for plain text format. This class provides an alternative to
+	 * the <code>TextConverter.export()</code> static method for exporting plain text,
+	 * useful if you need to customize the export by changing the paragraphSeparator
+	 * or stripDiscretionaryHyphens options. The PlainTextExporter class's 
+	 * <code>export()</code> method results in the 
+	 * same output string as the <code>TextConverter.export()</code> static method 
+	 * if the two properties of the PlainTextExporter class, the <code>paragraphSeparator</code>
+	 * and the <code>stripDiscretionaryHyphens</code> properties, contain their
+	 * default values of <code>"\n"</code> and <code>true</code>, respectively.
+	 * @includeExample examples\PlainTextExporter_example.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class PlainTextExporter implements ITextExporter	
+	{
+		private var _stripDiscretionaryHyphens:Boolean;
+		private var _paragraphSeparator:String;
+		
+		static private var _discretionaryHyphen:String = String.fromCharCode(0x00AD);
+		
+		/**
+		 * Constructor 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		public function PlainTextExporter()
+		{
+			_stripDiscretionaryHyphens = true;
+			_paragraphSeparator = "\n";
+		}
+		 
+		/** This flag indicates whether discretionary hyphens in the text should be stripped during the export process.
+		 * Discretionary hyphens, also known as "soft hyphens", indicate where to break a word in case the word must be
+		 * split between two lines. The Unicode character for discretionary hyphens is <code>\u00AD</code>.
+		 * <p>If the <code>stripDiscretionaryHyphens</code> property is set to <code>true</code>, discretionary hyphens that are in the original text will not be in the exported text, 
+		 * even if they are part of the original text. If <code>false</code>, discretionary hyphens will be in the exported text, 
+		 * The default value is <code>true</code>.</p>
+  		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get stripDiscretionaryHyphens():Boolean
+		{
+			return _stripDiscretionaryHyphens;
+			
+		}
+		public function set stripDiscretionaryHyphens(value:Boolean):void
+		{
+			_stripDiscretionaryHyphens = value;
+		}
+
+		/** Specifies the character sequence used (in a text flow's plain-text equivalent) to separate paragraphs.
+	    	 * The paragraph separator is not added after the last paragraph. The default value is "\n". 
+  		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSeparator():String
+		{ return _paragraphSeparator; }
+		public function set paragraphSeparator(value:String):void
+		{
+			_paragraphSeparator = value;
+		}
+
+		/** 
+		 * Export the contents of a TextFlow object to plain text.
+		 * The values of the <code>paragraphSeparator</code>
+		 * and the <code>stripDiscretionaryHyphens</code> properties
+		 * affect the output produced by this method.
+		 * @param source	the text flow object to export
+		 * @param conversionType 	The type to return (STRING_TYPE). This 
+		 * parameter accepts only one value: <code>ConversionType.STRING_TYPE</code>,
+		 * but is necessary because this class implements the ITextExporter
+		 * interface. The interface method, <code>ITextExporter.export()</code>, requires 
+		 * this parameter.
+		 * @return Object	the exported content
+		 * 
+		 * @see #paragraphSeparator
+		 * @see #stripDiscretionaryHyphens
+		 * @see ConversionType#STRING_TYPE
+  		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function export(source:TextFlow, conversionType:String):Object
+		{
+			if (conversionType == ConversionType.STRING_TYPE)
+				return exportToString(source);
+			return null;
+		}
+		
+		/** Export text content as a string
+		 * @param source	the text to export
+		 * @return String	the exported content
+		 * 
+  		 * @private
+		 */
+		protected function exportToString(source:TextFlow):String
+		{
+			var rslt:String = "";
+			var leaf:FlowLeafElement = source.getFirstLeaf(); 
+			
+			while (leaf)
+			{
+            	var p:ParagraphElement = leaf.getParagraph();
+            	while (true)
+            	{
+            		var curString:String = leaf.text;
+            		
+            		//split out discretionary hyphen and put string back together
+            		if (_stripDiscretionaryHyphens)
+            		{
+						var temparray:Array = curString.split(_discretionaryHyphen);
+						curString = temparray.join("");
+            		}
+					
+	               	rslt += curString;
+					var nextLeaf:FlowLeafElement = leaf.getNextLeaf(p);
+					if (!nextLeaf)
+						break; // end of para
+					
+					leaf = nextLeaf;
+            	}
+            	
+            	leaf = leaf.getNextLeaf();
+            	if (leaf) // not the last para
+                   	rslt += _paragraphSeparator; 
+   			}
+   			return rslt;
+		}
+ 	}
+}
\ No newline at end of file
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextImporter.as
new file mode 100755
index 0000000..e02cee9
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/PlainTextImporter.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 flashx.textLayout.conversion
+{
+	//import container.TextFrame;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.DivElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flash.display.DisplayObjectContainer;
+	
+	[ExcludeClass]
+	/** 
+	 * @private
+	 * PlainText import filter. Use this to import simple unformatted Unicode text.
+	 * Newlines will be converted to paragraphs. Using the PlainTextImporter directly
+	 * is equivalent to calling TextConverter.importToFlow(TextConverter.PLAIN_TEXT_FORMAT).
+	 */
+	internal class PlainTextImporter implements ITextImporter
+	{
+		protected var _config:IConfiguration;
+		
+		/** Constructor */
+		public function PlainTextImporter(config:IConfiguration =  null)
+		{
+			_config = config;
+		}
+		
+		/** Import text content, from an external source, and convert it into a TextFlow.
+		 * @param source		source data to convert, may be string or XML
+		 * @return TextFlow that was created from the source.
+		 */
+		public function importToFlow(source:Object):TextFlow
+		{
+			if (source is String)
+				return importFromString(String(source));
+			return null;
+		}
+		
+		// LF or CR or CR+LF. Equivalently, LF or CR, the latter optionally followed by LF
+		private static const _newLineRegex:RegExp = /\u000A|\u000D\u000A?/g;
+		
+		/** Import text content, from an external source, and convert it into a TextFlow.
+		 * @param source		source data to convert
+		 * @return textFlows[]	an array of TextFlow objects that were created from the source.
+		 */
+		protected function importFromString(source:String):TextFlow
+		{
+			var paragraphStrings:Array = source.split(_newLineRegex);
+
+			var textFlow:TextFlow = new TextFlow(_config);
+			var paraText:String;
+			for each (paraText in paragraphStrings)
+			{
+				var paragraph:ParagraphElement  = new ParagraphElement();
+				var span:SpanElement = new SpanElement();
+				span.replaceText(0, 0, paraText);
+				paragraph.replaceChildren(0, 0, span);			
+				textFlow.replaceChildren(textFlow.numChildren, textFlow.numChildren, paragraph);
+			}
+			return textFlow;			
+		}
+
+		/** Errors encountered while parsing. 
+		 * Value is a vector of Strings.
+		 */
+		public function get errors():Vector.<String>
+		{
+			return null;
+		}
+		
+		/** Errors will cause exceptions if throwOnError is true. */
+		public function get throwOnError():Boolean
+		{
+			return false;
+		}
+		
+		/** Does nothing.  get always returns false */
+		public function set throwOnError(value:Boolean):void
+		{
+			
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/SingletonAttributeImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/SingletonAttributeImporter.as
new file mode 100755
index 0000000..361caae
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/SingletonAttributeImporter.as
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	[ExcludeClass]
+	/**
+	 * @private  
+	 */
+	internal class SingletonAttributeImporter implements IFormatImporter
+	{
+		private var _keyToMatch:String;
+		private var _rslt:String = null;
+		
+		public function SingletonAttributeImporter(key:String)
+		{ _keyToMatch =  key; }
+		public function reset():void
+		{ _rslt = null; }
+		public function get result():Object
+		{ return _rslt; }
+		public function importOneFormat(key:String,val:String):Boolean
+		{
+			if (key == _keyToMatch)
+			{
+				_rslt = val;
+				return true;
+			}
+			return false; 
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/TLFormatImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/TLFormatImporter.as
new file mode 100755
index 0000000..f9ecbef
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/TLFormatImporter.as
@@ -0,0 +1,65 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.debug.assert;
+	[ExcludeClass]
+	/**
+	 * @private  
+	 */
+	public class TLFormatImporter implements IFormatImporter
+	{
+		private var _classType:Class;
+		private var _description:Object;
+		
+		private var _rslt:Object;
+		
+		public function TLFormatImporter(classType:Class,description:Object)
+		{ 
+			_classType = classType;
+			_description = description;
+		}
+		
+		public function get classType():Class
+		{ return _classType; }
+		
+		public function reset():void
+		{ 
+			_rslt = null;
+		}
+		public function get result():Object
+		{ 
+			return _rslt; 
+		}
+		public function importOneFormat(key:String,val:String):Boolean
+		{ 
+			if (_description.hasOwnProperty(key))
+			{
+				if (_rslt == null)
+					_rslt = new _classType();
+	
+				CONFIG::debug { assert((_description[key] as Property) != null,"Bad description in TLFormatImporter"); }
+				_rslt[key] =  _description[key].setHelper(undefined,val);
+				return true;
+			}
+			return false; 
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/TextConverter.as b/textLayout_conversion/src/flashx/textLayout/conversion/TextConverter.as
new file mode 100755
index 0000000..1e71d7f
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/TextConverter.as
@@ -0,0 +1,499 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.IConfiguration;
+	
+	/** 
+	 * This is the gateway class for handling import and export. It serves as a unified access point to the 
+	 * conversion functionality in the Text Layout Framework.
+	 * @includeExample examples\TextConverter_example.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class TextConverter
+	{
+		/** 
+		 * HTML format.
+		 * Use this for importing from, or exporting to, a TextFlow using the HTML fomat.
+		 * The Text Layout Framework HTML supports a subset of the tags and attributes supported by
+		 * the TextField class in the <code>flash.text</code> package.
+		 * <p>The following table lists the HTML tags and attributes supported for the import
+		 * and export process (tags and attributes supported by TextField, but not supported by 
+		 * the Text Layout Framework are specifically described as not supported):</p>
+		 * 
+		 * 
+		 * <table class="innertable" width="640">
+		 * 
+		 * <tr>
+		 * 
+		 * <th>
+		 * Tag
+		 * </th>
+		 * 
+		 * <th>
+		 * Description
+		 * </th>
+		 * 
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Anchor tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;a&gt;</code> tag creates a hypertext link and supports the following attributes:
+		 * <ul>
+		 * 
+		 * <li>
+		 * <code>target</code>: Specifies the name of the target window where you load the page. 
+		 * Options include <code>_self</code>, <code>_blank</code>, <code>_parent</code>, and 
+		 * <code>_top</code>. The <code>_self</code> option specifies the current frame in the current window, 
+		 * <code>_blank</code> specifies a new window, <code>_parent</code> specifies the parent of the 
+		 * current frame, and <code>_top</code> specifies the top-level frame in the current window. 
+		 * </li>
+		 *
+		 * <li>
+		 * <code>href</code>: Specifies a URL. The URL can 
+		 * be either absolute or relative to the location of the SWF file that 
+		 * is loading the page. An example of an absolute reference to a URL is 
+		 * <code>http://www.adobe.com</code>; an example of a relative reference is 
+		 * <code>/index.html</code>. Absolute URLs must be prefixed with 
+		 * http://; otherwise, Flash treats them as relative URLs. 
+		 * <strong>Note: Unlike the TextField class, </strong>ActionScript <code>link</code> events 
+		 * are not supported. Neither are
+		 * <code>a:link</code>, <code>a:hover</code>, and <code>a:active</code> styles.
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Bold tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;b&gt;</code> tag renders text as bold. A bold typeface must be available for the font used.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Break tag
+		 * </td>
+		 * <td>
+		 * The <code>&lt;br&gt;</code> tag creates a line break in the text.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Font tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;font&gt;</code> tag specifies a font or list of fonts to display the text.The font tag 
+		 * supports the following attributes:
+		 * <ul>
+		 * 
+		 * <li>
+		 * <code>color</code>: Only hexadecimal color (<code>#FFFFFF</code>) values are supported. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>face</code>: Specifies the name of the font to use. As shown in the following example, 
+		 * you can specify a list of comma-delimited font names, in which case Flash Player selects the first available 
+		 * font. If the specified font is not installed on the local computer system or isn't embedded in the SWF file, 
+		 * Flash Player selects a substitute font. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>size</code>: Specifies the size of the font. You can use absolute pixel sizes, such as 16 or 18 
+		 * or relative point sizes, such as +2 or -4. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>letterspacing</code>: Specifies the tracking (manual kerning) in pixels to be applied to the right of each character. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>kerning</code>: Specifies whether kerning is enabled or disabled. A non-zero value enables kerning, while zero disables it.  
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Image tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;img&gt;</code> tag lets you embed external image files (JPEG, GIF, PNG), SWF files, and 
+		 * movie clips inside text.  
+		 * 
+		 *  <p>The <code>&lt;img&gt;</code> tag supports the following attributes: </p>
+		 * 
+		 * <ul >
+		 * 
+		 * <li>
+		 * <code>src</code>: Specifies the URL to an image or SWF file, or the linkage identifier for a movie clip 
+		 * symbol in the library. This attribute is required; all other attributes are optional. External files (JPEG, GIF, PNG, 
+		 * and SWF files) do not show until they are downloaded completely. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>width</code>: The width of the image, SWF file, or movie clip being inserted, in pixels. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>height</code>: The height of the image, SWF file, or movie clip being inserted, in pixels. 
+		 * </li>
+		 * </ul>
+		 * <p><strong>Note: </strong> Unlike the TextField class, the following attributes are not supported:
+		 * <code>align</code>, <code>hspace</code>, <code>vspace</code>,  <code>id</code>, and <code>checkPolicyFile</code>.</p>
+		 *
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Italic tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;i&gt;</code> tag displays the tagged text in italics. An italic typeface must be available 
+		 * for the font used.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * <em>List item tag</em>
+		 * </td>
+		 * 
+		 * <td>
+		 * <strong>Note: </strong> Unlike the TextField class, the List item tag is not supported.
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Paragraph tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;p&gt;</code> tag creates a new paragraph. 
+		 * 
+		 * The <code>&lt;p&gt;</code> tag supports the following attributes:
+		 * <ul >
+		 * 
+		 * <li>
+		 * align: Specifies alignment of text within the paragraph; valid values are <code>left</code>, <code>right</code>, <code>justify</code>, and <code>center</code>. 
+		 * </li>
+		 * 
+		 * <li>
+		 * class: Specifies a class name that can be used for styling 
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Span tag
+		 * </td>
+		 * 
+		 * <td>
+		 * 
+		 * The <code>&lt;span&gt;</code> tag supports the following attributes:
+		 * 
+		 * <ul>
+		 * 
+		 * <li>
+		 * class: Specifies a class name that can be used for styling. While span tags are often used to set a style defined in a style sheet,
+		 * TLFTextField instances do not support style sheets. The span tag is available for TLFTextField instances to refer to a class with 
+		 * style properties.</li>
+		 * <li> You can also put properties directly in the span tag: 
+		 * <code>&lt;span fontFamily="Arial"&gt;Hi there&lt;/span&gt;</code>. However, nested span tags are not supported.
+		 * </li>
+		 * 
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Text format tag
+		 * </td>
+		 * 
+		 * <td>
+		 *  <p>The <code>&lt;textformat&gt;</code> tag lets you use a subset of paragraph formatting 
+		 * properties of the TextFormat class within text fields, including line leading, indentation, 
+		 * margins, and tab stops. You can combine <code>&lt;textformat&gt;</code> tags with the 
+		 * built-in HTML tags. </p>
+		 * 
+		 *  <p>The <code>&lt;textformat&gt;</code> tag has the following attributes: </p>
+		 * <ul >
+		 * 
+		 * 
+		 * <li>
+		 * <code>indent</code>: Specifies the indentation from the left margin to the first character 
+		 * in the paragraph; corresponds to <code>TextFormat.indent</code>. Both positive and negative 
+		 * numbers are acceptable. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>blockindent</code>: Specifies the indentation applied to all lines of the paragraph.
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>leftmargin</code>: Specifies the left margin of the paragraph, in points; corresponds 
+		 * to <code>TextFormat.leftMargin</code>. 
+		 * </li>
+		 * 
+		 * <li>
+		 * <code>rightmargin</code>: Specifies the right margin of the paragraph, in points; corresponds 
+		 * to <code>TextFormat.rightMargin</code>. 
+		 * </li>
+		 * 
+		 * 	<li>
+		 * <code>leading</code>: Specifies the leading (line height) measured in pixels between a line's ascent and the previous line's descent
+		 * </li>
+		 * 
+		 * 	<li>
+		 * <code>tabstops</code>: Specifies a comma-separated list of tab stop positions for the paragraph. 
+		 * </li>
+		 * </ul>
+		 * 
+		 * </td>
+		 * </tr>
+		 * 
+		 * <tr>
+		 * 
+		 * <td>
+		 * Underline tag
+		 * </td>
+		 * 
+		 * <td>
+		 * The <code>&lt;u&gt;</code> tag underlines the tagged text.
+		 * </td>
+		 * </tr>
+		 * 
+		 * </table>
+
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const TEXT_FIELD_HTML_FORMAT:String = "textFieldHTMLFormat";
+
+		/** 
+		 * Plain text format.
+		 * Use this for creating a TextFlow from a simple, unformatted String, 
+		 * or for creating a simple, unformatted String from a TextFlow.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const PLAIN_TEXT_FORMAT:String = "plainTextFormat";
+
+		/** 
+		 * TextLayout Format.
+		 * Use this for importing from, or exporting to, a TextFlow using the TextLayout markup format.
+		 * Text Layout format will detect the following errors:
+		 * <ul>
+		 * <li>Unexpected namespace</li>
+		 * <li>Unknown element</li>
+		 * <li>Unknown attribute</li>
+		 * </ul>
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const TEXT_LAYOUT_FORMAT:String = "textLayoutFormat";
+	
+		/** 
+		 * Creates a TextFlow from source content in a specified format.
+		 * Supported formats include HTML, plain text, and TextLayout Markup.
+		 * <p>Use one of the four static constants supplied with this class
+		 * to specify the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * @param source	Source content
+		 * @param format	Format of source content
+		 * @param config    IConfiguration to use when creating new TextFlows
+		 * @return TextFlow that was created from the source.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function importToFlow(source:Object, format:String, config:IConfiguration = null) : TextFlow
+		{
+			var parser:ITextImporter = getImporter(format, config);
+			return parser.importToFlow(source);
+		}
+		
+		/** 
+		 * Exports a TextFlow to a specified format. Supported formats
+		 * include FXG, HTML, plain text, and TextLayout Markup.
+		 * <p>Use one of the four static constants supplied with this class
+		 * to specify the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * <p>Specify the type of the exported data in the <code>conversionType</code> parameter 
+		 * with one of the two static constants supplied by the ConversionType class:
+		 * <ul>
+		 * <li>ConversionType.STRING_TYPE</li>
+		 * <li>ConversionType.XML_TYPE</li>
+		 * </ul>
+		 * </p>
+		 * 
+		 * Returns a representation of the TextFlow in the specified format.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param source	Source content
+		 * @param format	Output format
+		 * @param conversionType	Type of exported data
+		 * @return Object	Exported form of the TextFlow
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 * @see flashx.textLayout.conversion.ConversionType
+		 */
+		public static function export(source:TextFlow, format:String, conversionType:String) : Object
+		{
+			var exporter:ITextExporter = getExporter(format);
+			return exporter.export(source, conversionType);
+		}
+		
+		/** 
+		 * Creates an import filter. 
+		 * Returns an import filter, which you can then use to import from a 
+		 * source string or XML object to a TextFlow. Use this function
+		 * if you have many separate imports to perform, or if you want to 
+		 * handle errors during import. It is equivalent to calling 
+		 * <code>flashx.textLayout.conversion.TextConverter.importToFlow()</code>.
+		 * <p>Use one of the four static constants supplied with this class
+		 * to specify the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * @includeExample examples\getImporter_example.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param format	Format of source content.  Use constants from flashx.textLayout.conversion.TextConverter.TEXT_LAYOUT_FORMAT, PLAIN_TEXT_FORMAT, TEXT_FIELD_HTML_FORMAT etc.
+		 * @param config    configuration to use during this import.  null means take the current default.
+		 * @return ITextImporter	Text filter that can import the source data
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function getImporter(format:String,config:IConfiguration =  null): ITextImporter
+		{
+			switch (format)
+			{
+				case TEXT_LAYOUT_FORMAT:
+					return new TextLayoutImporter(config);
+				case PLAIN_TEXT_FORMAT:
+					return new PlainTextImporter(config);
+				case TEXT_FIELD_HTML_FORMAT:
+					return new HtmlImporter(config);
+			}
+			return null;
+		}
+
+		/** 
+		 * Creates an export filter.
+		 * Returns an export filter, which you can then use to export from 
+		 * a TextFlow to a source string or XML object. Use this function if 
+		 * you have many separate exports to perform. It is equivalent to calling 
+		 * <code>flashx.textLayout.conversion.TextConverter.export()</code>.
+		 * <p>Use one of the four static constants supplied with this class
+		 * to specify the <code>format</code> parameter:
+		 * <ul>
+		 * <li>TextConverter.TEXT_FIELD_HTML_FORMAT</li>
+		 * <li>TextConverter.PLAIN_TEXT_FORMAT</li>
+		 * <li>TextConverter.TEXT_LAYOUT_FORMAT</li>
+		 * </ul>
+		 * </p>
+		 * @includeExample examples\getExporter_example.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 * @param format	Target format for exported data
+		 * @return ITextExporter	Text filter that can export in the specified format
+		 * @see #TEXT_FIELD_HTML_FORMAT
+		 * @see #PLAIN_TEXT_FORMAT
+		 * @see #TEXT_LAYOUT_FORMAT
+		 */
+		public static function getExporter(format:String) : ITextExporter
+		{
+			switch (format)
+			{
+				case TEXT_LAYOUT_FORMAT:
+					return new TextLayoutExporter();
+				case PLAIN_TEXT_FORMAT:
+					return new PlainTextExporter();
+				case TEXT_FIELD_HTML_FORMAT:
+					return new HtmlExporter();
+			}
+			
+			return null;
+		}
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutExporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutExporter.as
new file mode 100755
index 0000000..8f24cad
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutExporter.as
@@ -0,0 +1,251 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion
+{
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.DivElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowValueHolder;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.WhiteSpaceCollapse;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** 
+	 * @private
+	 * Export filter for TextLayout format. 
+	 */
+	internal class TextLayoutExporter extends BaseTextLayoutExporter
+	{	
+		private static var nameCounter:int = 0;
+		static private var _formatDescription:Object= TextLayoutFormat.description;
+
+		private var queuedExport:Object = null;
+		
+		public function TextLayoutExporter()
+		{
+			super(new Namespace("http://ns.adobe.com/textLayout/2008"), null, TextLayoutImporter.defaultConfiguration);
+		}
+		
+		override protected function clear():void
+		{
+			nameCounter = 0;
+			queuedExport = null;
+		}
+		
+		/** Export text content of a TextFlow into TextLayout format.
+		 * @param source	the text to export
+		 * @return XML	the exported content
+		 */
+		protected override function exportToXML(textFlow:TextFlow) : XML
+		{
+			var result:XML = super.exportToXML(textFlow);
+			var queuedXML:XMLList = exportQueuedObjects();
+			if (queuedXML)
+				result.appendChild(queuedXML);
+			return result;
+		}
+		
+		private function exportQueuedObjects():XMLList
+		{
+			if (!queuedExport)
+				return null;
+			
+			// pump out the queued objects
+			var result:XMLList = new XMLList();
+			for  (var idName:String in queuedExport) {
+				var objectToExport:Object = queuedExport[idName];
+				var output:XMLList = new XMLList();
+				if (objectToExport is FlowValueHolder) {
+					var characterFormatXML:XML = new XML("<format/>");
+					characterFormatXML.setNamespace(flowNS);
+					output += characterFormatXML;
+					output.@id = idName;
+					exportStyles(output, objectToExport.coreStyles, formatDescription);
+					exportStyles(output, objectToExport.userStyles);
+				}
+				result += output;
+			}
+			return result;
+		}
+		
+		/** Get additional objects that are required for export
+		 * The subject may have dependent objects that will need to be exported, in addition
+		 * to the subject itself.
+		 * @return XML	array of Objects to export
+		 */
+		private function queueForExport(object:Object, name:String):void
+		{
+			if (!queuedExport)
+				queuedExport = new Object();
+				
+			queuedExport[name] = object;
+		}
+		
+		static private const brTabRegEx:RegExp = new RegExp("[" + "\u2028" + "\t" + "]"); // Doesn't /\u2028\t/ work?
+		
+		/** Gets the regex that specifies characters to be replaced with XML elements
+		 *  Note: Each match is a single character 
+		 */
+		protected override function get spanTextReplacementRegex():RegExp
+		{
+			return brTabRegEx;
+		}
+		
+		/** Gets the xml element used to represent a character in the export format
+		 */
+		protected override function getSpanTextReplacementXML(ch:String):XML
+		{
+			var replacementXML:XML;
+			if (ch == '\u2028')
+				replacementXML = <br/>;
+			else if (ch == '\t')
+				replacementXML = <tab/>;
+			else
+			{
+				CONFIG::debug {assert(false, "Did not recognize character to be replaced with XML"); }
+				return null;			
+			}
+		
+			replacementXML.setNamespace(flowNS);
+			return replacementXML;	
+		}
+		
+		protected override function exportFlowElement(flowElement:FlowElement):XMLList
+		{
+			var rslt:XMLList = super.exportFlowElement(flowElement);
+			
+			var coreStyles:Object = flowElement.coreStyles;
+			if (coreStyles)
+			{
+				// WhiteSpaceCollapse attribute should never be exported (except on TextFlow -- handled separately)
+				delete coreStyles[TextLayoutFormat.whiteSpaceCollapseProperty.name];
+				exportStyles(rslt, coreStyles, formatDescription);
+			}
+			
+			// export id and styleName
+			if (flowElement.id != null)
+				rslt.@["id"] = flowElement.id;
+			if (flowElement.styleName != null)
+				rslt.@["styleName"] = flowElement.styleName;
+			// export any user defined styles
+			var styles:Object = flowElement.userStyles;
+			if (styles)
+				exportStyles(rslt, styles);
+				
+			return rslt;
+		}
+
+		/** Base functionality for exporting an Image. Exports as a FlowElement,
+		 * and exports image properties.
+		 * @param exporter	Root object for the export
+		 * @param image	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportImage(exporter:BaseTextLayoutExporter, image:InlineGraphicElement):XMLList
+		{
+			var output:XMLList = exportFlowElement(exporter, image);
+			
+			// output the img specific values
+			if (image.height !== undefined)
+				output.@height = image.height;
+			if (image.width !== undefined)
+				output.@width = image.width;
+		//	output.@rotation = image.rotation;  don't support rotation yet
+			if (image.source != null)
+				output.@source = image.source;
+			// FUTURE!!! output.@float = image.float;
+						
+			return output;
+		}
+
+		/** Base functionality for exporting a LinkElement. Exports as a FlowGroupElement,
+		 * and exports link properties.
+		 * @param exporter	Root object for the export
+		 * @param link	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportLink(exporter:BaseTextLayoutExporter, link:LinkElement):XMLList
+		{
+			var output:XMLList = exportFlowGroupElement(exporter, link);
+
+			if (link.href)
+				output.@href= link.href;
+				
+			if (link.target)
+				output.@target = link.target;
+				
+			return output;
+		}
+		
+		/** Base functionality for exporting a DivElement. Exports as a FlowContainerFormattedElement
+		 * @param exporter	Root object for the export
+		 * @param div	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportDiv(exporter:BaseTextLayoutExporter, div:DivElement):XMLList
+		{
+			return exportContainerFormattedElement(exporter, div);
+		}
+		
+		/** Base functionality for exporting a TCYElement. Exports as a FlowGroupElement
+		 * @param exporter	Root object for the export
+		 * @param tcy	Element to export
+		 * @return XMLList	XML for the element
+		 */
+		static public function exportTCY(exporter:BaseTextLayoutExporter, tcy:TCYElement):XMLList
+		{
+			return exportFlowGroupElement(exporter, tcy);
+		}
+		
+		/** Queues the object for export later, generates an ID for it, and returns
+		 * the ID.
+		 * @param exporter	Root object for the export
+		 * @param obj	Element to export
+		 * @return String	ID of the object
+		 */
+		static private function exportToName(exporter:BaseTextLayoutExporter, obj:Object):String
+		{
+			var newName:String = "ObjectID" + nameCounter.toString();
+			TextLayoutExporter(exporter).queueForExport(obj, newName);
+			nameCounter++;
+			return newName;
+		}
+		
+		override protected function get formatDescription():Object
+		{
+			return _formatDescription;
+		}		
+
+	}
+}
diff --git a/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutImporter.as b/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutImporter.as
new file mode 100755
index 0000000..c029e88
--- /dev/null
+++ b/textLayout_conversion/src/flashx/textLayout/conversion/TextLayoutImporter.as
@@ -0,0 +1,459 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.conversion 
+{
+	import __AS3__.vec.Vector;
+	
+	import flash.display.Shape;
+	import flash.text.engine.TextRotation;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.BreakElement;
+	import flashx.textLayout.elements.DivElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TabElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.EnumStringProperty;
+	import flashx.textLayout.property.NumberProperty;
+	import flashx.textLayout.property.StringProperty;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** 
+	 * @private
+	 * TextLayoutImporter converts from XML to TextLayout data structures and back.
+	 */ 	
+	public class TextLayoutImporter extends BaseTextLayoutImporter 
+	{
+		private static var _defaultConfiguration:ImportExportConfiguration;
+		
+		/** Default ImportExportConfiguration to use when none specified 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0 
+		*/
+		public static function get defaultConfiguration():ImportExportConfiguration
+		{
+			// The first call will force the import/export to include the standard components
+			if (!_defaultConfiguration)
+			{
+				_defaultConfiguration = new ImportExportConfiguration();
+				// shared by TextLayout and FXG markup
+	 			_defaultConfiguration.addIEInfo("TextFlow", TextFlow,        BaseTextLayoutImporter.parseTextFlow, BaseTextLayoutExporter.exportTextFlow, true);
+				_defaultConfiguration.addIEInfo("br", BreakElement,          BaseTextLayoutImporter.parseBreak, BaseTextLayoutExporter.exportFlowElement, false);
+				_defaultConfiguration.addIEInfo("p", ParagraphElement,       BaseTextLayoutImporter.parsePara, BaseTextLayoutExporter.exportParagraphFormattedElement, true);
+				_defaultConfiguration.addIEInfo("span", SpanElement,         BaseTextLayoutImporter.parseSpan, BaseTextLayoutExporter.exportSpan, false);
+				_defaultConfiguration.addIEInfo("tab", TabElement,           BaseTextLayoutImporter.parseTab, BaseTextLayoutExporter.exportFlowElement, false);
+				// shared by TextLayoutMarkup only
+				_defaultConfiguration.addIEInfo("tcy", TCYElement,           TextLayoutImporter.parseTCY, TextLayoutExporter.exportTCY, false);
+				_defaultConfiguration.addIEInfo("a", LinkElement,            TextLayoutImporter.parseLink, TextLayoutExporter.exportLink, false);
+	 			_defaultConfiguration.addIEInfo("div", DivElement,           TextLayoutImporter.parseDivElement, TextLayoutExporter.exportDiv, true);
+				_defaultConfiguration.addIEInfo("img", InlineGraphicElement, TextLayoutImporter.parseInlineGraphic, TextLayoutExporter.exportImage, false);							 
+				// customized link formats
+				_defaultConfiguration.addIEInfo(LinkElement.LINK_NORMAL_FORMAT_NAME,null,TextLayoutImporter.parseLinkNormalFormat,null, false);
+				_defaultConfiguration.addIEInfo(LinkElement.LINK_ACTIVE_FORMAT_NAME,null,TextLayoutImporter.parseLinkActiveFormat,null, false);
+				_defaultConfiguration.addIEInfo(LinkElement.LINK_HOVER_FORMAT_NAME, null,TextLayoutImporter.parseLinkHoverFormat, null, false);
+			}
+			
+			return _defaultConfiguration;
+		}
+		
+		/** Set the default configuration back to its original value 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+		public static function restoreDefaults():void
+		{
+			_defaultConfiguration = null;
+		}
+		
+				
+		protected var bindingsArray:Array;
+		
+		static private const _formatImporter:TLFormatImporter = new TLFormatImporter(TextLayoutFormatValueHolder,TextLayoutFormat.description);
+		static private const _idImporter:SingletonAttributeImporter = new SingletonAttributeImporter("id");
+		static private const _styleNameImporter:SingletonAttributeImporter = new SingletonAttributeImporter("styleName");
+		static private const _customFormatImporter:CustomFormatImporter = new CustomFormatImporter();
+		
+		static private const _flowElementFormatImporters:Array = [ _formatImporter,_idImporter,_styleNameImporter,_customFormatImporter ];
+
+		/** Constructor */
+		public function TextLayoutImporter(textFlowConfiguration:IConfiguration)
+		{
+			super(textFlowConfiguration, flowNS, defaultConfiguration);
+		}
+
+		override protected function clear():void
+		{
+			bindingsArray = null;
+			super.clear();
+		}
+		
+		private static function get flowNS():Namespace
+		{
+			return new Namespace("flow", "http://ns.adobe.com/textLayout/2008");
+		}
+		
+		/**  @private */
+		override protected function parseContent(rootStory:XML):TextFlow
+		{
+			// Capture all the top-level tags of interest that can be "bound"
+			// We have to do this because the attributes are applied at the point
+			// of calling something like:
+			// span.charAttrs = characterAttrs;
+			// At one time, we just set the variable to the parameter (in the setter),
+			// but now we're copying the data into a new object. This change does
+			// not allow for us to parse the bindings in any order. Hence, we
+			// will process the potential bindings objects first, then the
+			// TextFlow objects.
+			//
+			// Also note the use of "..*" below. We are using this to traverse the
+			// XML structure looking for particular tags and at the same time allow for
+			// any namespace. So, you might see something like <flow:TextContainer> or
+			// <TextContainer> and this code will capture both cases.
+			
+			var rootName:String = rootStory.name().localName;
+			var textFlowElement:XML = rootName == "TextFlow" ? rootStory : rootStory..*::TextFlow[0];
+			if (!textFlowElement)
+			{
+				reportError(GlobalSettings.resourceStringFunction("missingTextFlow")); 
+				return null;
+			}
+			if (!checkNamespace(textFlowElement))
+				return null;
+	
+			return parseTextFlow(this, textFlowElement);
+		}
+		
+		private function parseStandardFlowElementAttributes(flowElem:FlowElement,xmlToParse:XML,importers:Array = null):void
+		{
+			if (importers == null)
+				importers = _flowElementFormatImporters;
+			// all the standard ones have to be in importers - some check needed
+			parseAttributes(xmlToParse,importers);
+			flowElem.format = extractTextFormatAttributesHelper(flowElem.format,_formatImporter) as ITextLayoutFormat;
+
+			flowElem.id = _idImporter.result as String;
+			flowElem.styleName = _styleNameImporter.result as String;
+			flowElem.userStyles = _customFormatImporter.result as Dictionary;
+		}
+		
+
+		override public function createTextFlowFromXML(xmlToParse:XML, textFlow:TextFlow = null):TextFlow
+		{
+			// allocate the TextFlow and set the TextContainer's rootElement to it.
+			var newFlow:TextFlow = null;
+			if (xmlToParse.@["id"] != undefined)
+			{
+				var flowName:String = null;
+				flowName = xmlToParse.@["id"];
+				newFlow = getBoundObjNamed(flowName, TextFlow) as TextFlow;
+			}
+
+			if (!checkNamespace(xmlToParse))
+				return newFlow;
+
+			// allocate the TextFlow and initialize the container attributes
+			if (!newFlow)
+				newFlow = new TextFlow(_textFlowConfiguration);
+	
+			parseStandardFlowElementAttributes(newFlow,xmlToParse);
+			
+			// TextFlow can have CharacterFormat, ParagraphFormat and ContainerFormat children.  Filter them out here
+			parseFlowGroupElementChildren(xmlToParse, newFlow);
+			
+			CONFIG::debug { newFlow.debugCheckNormalizeAll() ; }
+			newFlow.tlf_internal::normalize();
+			
+			newFlow.tlf_internal::applyWhiteSpaceCollapse();
+			
+			return newFlow;
+		}
+		
+		public function createDivFromXML(xmlToParse:XML):DivElement
+		{
+			// add the div element to the parent
+			var divElem:DivElement = new DivElement();
+			
+			parseStandardFlowElementAttributes(divElem,xmlToParse);
+
+			return divElem;
+		}
+		
+		public override function createParagraphFromXML(xmlToParse:XML):ParagraphElement
+		{
+			var paraElem:ParagraphElement = new ParagraphElement();
+			parseStandardFlowElementAttributes(paraElem,xmlToParse);
+			return paraElem;
+		}
+		
+		public function createTCYFromXML(xmlToParse:XML):TCYElement
+		{
+			var tcyElem:TCYElement = new TCYElement();
+			parseStandardFlowElementAttributes(tcyElem,xmlToParse);
+			return tcyElem;
+		}
+		
+			
+		static internal const _linkDescription:Object = {
+			href : new StringProperty("href",null, false, null),
+			target : new StringProperty("target",null, false, null)
+		}
+		static private const _linkFormatImporter:TLFormatImporter = new TLFormatImporter(Dictionary,_linkDescription);
+		static private const _linkElementFormatImporters:Array = [ _linkFormatImporter, _formatImporter,_idImporter,_styleNameImporter,_customFormatImporter ];
+
+		/** Parse a LinkElement Block.
+		 * 
+		 * @param - importFilter:BaseTextLayoutImporter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Link
+		 * @param - parent:FlowBlockElement - the parent of the new Link
+		 * @return LinkElement - a new LinkElement and its children
+		 */
+		public function createLinkFromXML(xmlToParse:XML):LinkElement
+		{
+			var linkElem:LinkElement = new LinkElement();
+			parseStandardFlowElementAttributes(linkElem,xmlToParse,_linkElementFormatImporters);
+			if (_linkFormatImporter.result)
+			{
+				linkElem.href = _linkFormatImporter.result["href"] as String;
+				linkElem.target = _linkFormatImporter.result["target"] as String;
+			}
+
+			return linkElem;
+		}
+		
+		public override function createSpanFromXML(xmlToParse:XML):SpanElement
+		{
+			var spanElem:SpanElement = new SpanElement();
+			
+			parseStandardFlowElementAttributes(spanElem,xmlToParse);
+
+			return spanElem;
+		}
+		
+		static private const _imageDescription:Object = {
+			height:InlineGraphicElement.heightPropertyDefinition,
+			width:InlineGraphicElement.widthPropertyDefinition,
+			source: new StringProperty("source", null, false, null),
+			float: new StringProperty("float", null, false, null),
+			rotation: InlineGraphicElement.rotationPropertyDefinition }
+		
+		static private const _ilgFormatImporter:TLFormatImporter = new TLFormatImporter(Dictionary,_imageDescription);
+		static private const _ilgElementFormatImporters:Array = [ _ilgFormatImporter, _formatImporter/*,_boundTextLayoutFormatImporter*/,_idImporter,_styleNameImporter,_customFormatImporter ];
+
+		public function createInlineGraphicFromXML(xmlToParse:XML):InlineGraphicElement
+		{				
+			var imgElem:InlineGraphicElement = new InlineGraphicElement();
+			
+			parseStandardFlowElementAttributes(imgElem,xmlToParse,_ilgElementFormatImporters);
+			
+			if (_ilgFormatImporter.result)
+			{
+				var source:String = _ilgFormatImporter.result["source"];
+				imgElem.source = source;
+				
+				// if not defined then let InlineGraphic set its own default
+				imgElem.height = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.height,_ilgFormatImporter.result["height"]);
+				imgElem.width  = InlineGraphicElement.widthPropertyDefinition.setHelper(imgElem.width,_ilgFormatImporter.result["width"]);
+				/*	We don't support rotation yet because of bugs in the player. */		
+				// imgElem.rotation  = InlineGraphicElement.heightPropertyDefinition.setHelper(imgElem.rotation,_ilgFormatImporter.result["rotation"]);
+				imgElem.float = InlineGraphicElement.floatPropertyDefinition.setHelper(imgElem.float,_ilgFormatImporter.result["float"]);
+			}
+			
+			return imgElem;
+		}
+	
+		public function extractTextFormatAttributesHelper(curAttrs:Object, importer:TLFormatImporter):Object
+		{
+			return extractAttributesHelper(curAttrs,importer);
+		}
+
+		protected function parseNamedFormatDefinition(xmlToParse:XML, importer:TLFormatImporter) : void
+		{
+			if (!checkNamespace(xmlToParse))
+				return;
+			
+			var idName:String = xmlToParse.@id.toString();
+			if (idName == null || idName.length == 0)
+				return;
+				
+			importer.reset();
+			for each (var item:XML in xmlToParse.attributes())
+				importer.importOneFormat(item.name().localName,item.toString());
+			
+			if (!bindingsArray)
+				bindingsArray = new Array();
+			bindingsArray[idName] = importer.result ? importer.result : new importer.classType();
+		}
+		
+		// Find string in array
+		static private function arrayHasString(arr:Array, str:String):Boolean
+		{
+			for each (var item:String in arr)
+				if (str == item)
+					return true;
+			return false;
+		}
+		
+		// Return a "bindings" object. This method allows us to encounter a object via a binding
+		// (it appears within "{}" or we can encounter the actual tag (e.g, <CharacterFormat ... >). Either way
+		// this method will allocate an object with the given name, and assign the attributes as they become
+		// available in the BaseTextLayoutImportFilter.
+		internal function getBoundObjNamed(name:String, typeClass:Class):Object
+		{
+			CONFIG::debug {assert(name != null && name.length > 0, "null string for a bound object")}
+			if (!bindingsArray)
+				bindingsArray = new Array();
+			if (bindingsArray[name] == null) 
+			{
+				if (typeClass == TextFlow)
+					bindingsArray[name] = new typeClass(this._textFlowConfiguration);
+				else
+					bindingsArray[name] = new typeClass();
+ 			}
+
+			return bindingsArray[name];
+		}
+
+		/** Parse a TCY Block.
+		 * 
+		 * @param - importFilter:BaseTextLayoutImporter - parser object
+		 * @param - xmlToParse:XML - the xml describing the TCY Block
+		 * @param - parent:FlowBlockElement - the parent of the new TCY Block
+		 * @return TCYBlockElement - a new TCYBlockElement and its children
+		 */
+		static public function parseTCY(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var tcyElem:TCYElement = TextLayoutImporter(importFilter).createTCYFromXML(xmlToParse);
+			if (importFilter.addChild(parent, tcyElem))
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, tcyElem);
+				//if parsing an empty tcy, create a Span for it.
+				if (tcyElem.numChildren == 0)
+					tcyElem.addChild(new SpanElement());
+			}
+		}
+		
+				
+		/** Parse a LinkElement Block.
+		 * 
+		 * @param - importFilter:BaseTextLayoutImporter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Link
+		 * @param - parent:FlowBlockElement - the parent of the new Link
+		 * @return LinkElement - a new LinkElement and its children
+		 */
+		static public function parseLink(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var linkElem:LinkElement = TextLayoutImporter(importFilter).createLinkFromXML(xmlToParse);
+			if (importFilter.addChild(parent, linkElem))
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, linkElem);
+				//if parsing an empty link, create a Span for it.
+				if (linkElem.numChildren == 0)
+					linkElem.addChild(new SpanElement());
+			}
+		}
+		
+		public function createDictionaryFromXML(xmlToParse:XML):Dictionary
+		{
+			var formatImporters:Array = [ _customFormatImporter ];
+
+			// parse the TextLayoutFormat child object		
+			var formatList:XMLList = xmlToParse..*::TextLayoutFormat;
+			if (formatList.length() != 1)
+				reportError(GlobalSettings.resourceStringFunction("expectedExactlyOneTextLayoutFormat",[ xmlToParse.name() ]));
+			
+			var parseThis:XML = formatList.length() > 0 ? formatList[0] : xmlToParse;
+			parseAttributes(parseThis,formatImporters);
+			var styleDictionary:Dictionary = _customFormatImporter.result as Dictionary;
+
+			// Link style property values may have been brought through as literal String values. We need to convert
+			// them into typed values, so they get output as canonical translation of the value type into String. 
+			// The color property is an example, where it can get input in 3 different formats, but can only be output in one.
+			var description:Object = TextLayoutFormat.description;
+			for (var prop:String in description)
+			{
+				var val:* = styleDictionary[prop];
+				if (val !== undefined)
+				{
+					val = description[prop].setHelper(undefined,val)
+					if (val !== undefined)
+						styleDictionary[prop] = val;
+				}
+			}
+			
+			return styleDictionary;
+		}
+
+		static public function parseLinkNormalFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{ parent.linkNormalFormat = TextLayoutImporter(importFilter).createDictionaryFromXML(xmlToParse); }
+		static public function parseLinkActiveFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{ parent.linkActiveFormat = TextLayoutImporter(importFilter).createDictionaryFromXML(xmlToParse); }
+		static public function parseLinkHoverFormat(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{ parent.linkHoverFormat = TextLayoutImporter(importFilter).createDictionaryFromXML(xmlToParse); }
+
+		/** Parse the <div ...> tag and all its children
+		 * 
+		 * @param - importFilter:BaseTextLayoutImportFilter - parser object
+		 * @param - xmlToParse:XML - the xml describing the Div
+		 * @param - parent:FlowBlockElement - the parent of the new Div
+		 */
+		static public function parseDivElement(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var divElem:DivElement = TextLayoutImporter(importFilter).createDivFromXML(xmlToParse);
+			if (importFilter.addChild(parent, divElem))
+			{
+				importFilter.parseFlowGroupElementChildren(xmlToParse, divElem);
+				// we can't have a <div> tag w/no children... so, add an empty paragraph
+				if (divElem.numChildren == 0)
+					divElem.addChild(new ParagraphElement());
+			}
+		}
+
+		/** Parse a leaf element, the <img ...>  tag.
+		 * 
+		 * @param - importFilter:BaseTextLayoutImporter - parser object
+		 * @param - xmlToParse:XML - the xml describing the InlineGraphic FlowElement
+		 * @param - parent:FlowBlockElement - the parent of the new image FlowElement
+		 */
+		static public function parseInlineGraphic(importFilter:BaseTextLayoutImporter, xmlToParse:XML, parent:FlowGroupElement):void
+		{
+			var ilg:InlineGraphicElement = TextLayoutImporter(importFilter).createInlineGraphicFromXML(xmlToParse);
+			importFilter.addChild(parent, ilg);
+		}
+	}
+}
+
diff --git a/textLayout_core/.actionScriptProperties b/textLayout_core/.actionScriptProperties
new file mode 100755
index 0000000..16ab5b0
--- /dev/null
+++ b/textLayout_core/.actionScriptProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<actionScriptProperties mainApplicationPath="textLayout_core.as" projectUUID="674ab66b-95bb-4550-a70c-4569862c3193" version="6">
+  <compiler additionalCompilerArguments="-locale en_US -include-namespaces library://ns.adobe.com/flashx/textLayout -load-config+=../../config.xml" autoRSLOrdering="true" copyDependentFiles="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" sourceFolderPath="src" strict="true" targetPlayerVersion="10.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+    <compilerSourcePath/>
+    <libraryPath defaultLinkType="0">
+      <libraryPathEntry kind="4" path="">
+        <excludedEntries>
+          <libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="4" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/rpc_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="rpc_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="2" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/framework_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="framework_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="1" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/textLayout.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/textLayout_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="textLayout_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="3" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/spark_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="spark_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
+        </excludedEntries>
+      </libraryPathEntry>
+    </libraryPath>
+    <sourceAttachmentPath/>
+  </compiler>
+  <applications>
+    <application path="textLayout_core.as"/>
+  </applications>
+  <modules/>
+  <buildCSSFiles/>
+</actionScriptProperties>
diff --git a/textLayout_core/.flexLibProperties b/textLayout_core/.flexLibProperties
new file mode 100755
index 0000000..9740fb7
--- /dev/null
+++ b/textLayout_core/.flexLibProperties
@@ -0,0 +1,25 @@
+# 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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<flexLibProperties includeAllClasses="false" version="3">
+  <includeClasses>
+    <classEntry path="flashx.textLayout.CoreClasses"/>
+  </includeClasses>
+  <includeResources/>
+  <namespaceManifests>
+    <namespaceManifestEntry manifest="../manifest.xml" namespace="library://ns.adobe.com/flashx/textLayout"/>
+  </namespaceManifests>
+</flexLibProperties>
diff --git a/textLayout_core/.project b/textLayout_core/.project
new file mode 100755
index 0000000..4941a7c
--- /dev/null
+++ b/textLayout_core/.project
@@ -0,0 +1,34 @@
+<?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.
+-->
+<projectDescription>
+	<name>textLayout_core</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.adobe.flexbuilder.project.flexbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
+		<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
+	</natures>
+</projectDescription>
diff --git a/textLayout_core/manifest.xml b/textLayout_core/manifest.xml
new file mode 100755
index 0000000..d72337c
--- /dev/null
+++ b/textLayout_core/manifest.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<componentPackage>
+  <component id="TextLayoutFormat" class="flashx.textLayout.formats.TextLayoutFormat" />
+  <component id="div" class="flashx.textLayout.elements.DivElement" />
+  <component id="img" class="flashx.textLayout.elements.InlineGraphicElement" />
+  <component id="a" class="flashx.textLayout.elements.LinkElement" />
+  <component id="p" class="flashx.textLayout.elements.ParagraphElement" />
+  <component id="br" class="flashx.textLayout.elements.BreakElement" />
+  <component id="tab" class="flashx.textLayout.elements.TabElement" />
+  <component id="tcy" class="flashx.textLayout.elements.TCYElement" />
+  <component id="span" class="flashx.textLayout.elements.SpanElement" />
+  <component id="TextFlow" class="flashx.textLayout.elements.TextFlow" />
+</componentPackage>
diff --git a/textLayout_core/src/flashx/textLayout/BuildInfo.as b/textLayout_core/src/flashx/textLayout/BuildInfo.as
new file mode 100755
index 0000000..ab59413
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/BuildInfo.as
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout
+{
+	[ExcludeClass]
+	/**
+	 * Contains identifying information for the current build. 
+	 * This may not be the form that this information is presented in the final API.
+	 */
+	public class BuildInfo
+	{
+		/**
+		 * Contains the current version number. 
+		 */
+		public static const VERSION:String = "1.0";
+		
+		/**
+		 * Contains the current build number. 
+		 * It is static and can be called with <code>BuildInfo.kBuildNumber</code>
+		 * <p>String Format: "BuildNumber (Changelist)"</p>
+		 */
+		public static const kBuildNumber:String = "595 (738907)";
+		
+		/**
+		 * Contains the branch name. 
+		 */
+		public static const kBranch:String = "1.0";
+
+		/**
+		 * @private 
+		 */
+		public static const AUDIT_ID:String = "<AdobeIP 0000486>";
+		
+		/**
+		 * @private 
+		 */
+		public function dontStripAuditID():String
+		{
+			return AUDIT_ID;
+		}
+	}
+}	// package
diff --git a/textLayout_core/src/flashx/textLayout/CoreClasses.as b/textLayout_core/src/flashx/textLayout/CoreClasses.as
new file mode 100755
index 0000000..d86b5cb
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/CoreClasses.as
@@ -0,0 +1,147 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout
+{
+ 	internal class CoreClasses
+	{
+		import flashx.textLayout.tlf_internal; tlf_internal;
+		
+		import flashx.textLayout.accessibility.TextAccImpl; TextAccImpl;
+		
+		import flashx.textLayout.BuildInfo; BuildInfo;
+
+		import flashx.textLayout.compose.BaseCompose; BaseCompose;
+		import flashx.textLayout.compose.ComposeState; ComposeState;
+		import flashx.textLayout.compose.FlowComposerBase; FlowComposerBase;
+		import flashx.textLayout.compose.FlowDamageType; FlowDamageType;
+		import flashx.textLayout.compose.IFlowComposer; IFlowComposer;
+		import flashx.textLayout.compose.ITextLineCreator; ITextLineCreator;
+		import flashx.textLayout.compose.ISWFContext; ISWFContext;
+		import flashx.textLayout.compose.IVerticalJustificationLine; IVerticalJustificationLine;
+		import flashx.textLayout.compose.Parcel; Parcel;
+		import flashx.textLayout.compose.ParcelList; ParcelList;
+		import flashx.textLayout.compose.SimpleCompose; SimpleCompose;
+		import flashx.textLayout.compose.TextFlowLine; TextFlowLine;
+		import flashx.textLayout.compose.TextFlowLineLocation; TextFlowLineLocation;
+		import flashx.textLayout.compose.TextLineRecycler; TextLineRecycler;
+		import flashx.textLayout.compose.StandardFlowComposer; StandardFlowComposer;
+		import flashx.textLayout.compose.VerticalJustifier; VerticalJustifier;
+		
+		import flashx.textLayout.container.ColumnState; ColumnState;		
+		import flashx.textLayout.container.ContainerController; ContainerController;
+		import flashx.textLayout.container.ISandboxSupport; ISandboxSupport;
+		import flashx.textLayout.container.ScrollPolicy; ScrollPolicy;
+				
+		import flashx.textLayout.debug.assert;
+		import flashx.textLayout.debug.Debugging; Debugging;
+		
+		import flashx.textLayout.edit.EditingMode; EditingMode;
+		import flashx.textLayout.edit.IInteractionEventHandler; IInteractionEventHandler;
+		import flashx.textLayout.edit.ISelectionManager; ISelectionManager;
+		import flashx.textLayout.edit.SelectionFormat; SelectionFormat;
+		import flashx.textLayout.edit.SelectionState; SelectionState;
+		import flashx.textLayout.elements.TextRange; TextRange;
+		
+		import flashx.textLayout.elements.BreakElement; BreakElement;
+		import flashx.textLayout.elements.Configuration; Configuration;
+		import flashx.textLayout.elements.ContainerFormattedElement; ContainerFormattedElement;
+		import flashx.textLayout.elements.DivElement; DivElement;
+		import flashx.textLayout.elements.FlowElement; FlowElement;
+		import flashx.textLayout.elements.FlowGroupElement; FlowGroupElement;
+		import flashx.textLayout.elements.FlowLeafElement; FlowLeafElement;
+		import flashx.textLayout.elements.GlobalSettings; GlobalSettings;
+		import flashx.textLayout.elements.IConfiguration; IConfiguration;
+		import flashx.textLayout.elements.IFormatResolver; IFormatResolver;
+		import flashx.textLayout.elements.InlineGraphicElement; InlineGraphicElement;
+		import flashx.textLayout.elements.InlineGraphicElementStatus; InlineGraphicElementStatus;
+		import flashx.textLayout.elements.LinkElement; LinkElement;
+		import flashx.textLayout.elements.LinkState; LinkState;
+		import flashx.textLayout.elements.OverflowPolicy; OverflowPolicy;
+		import flashx.textLayout.elements.ParagraphElement; ParagraphElement;
+		import flashx.textLayout.elements.ParagraphFormattedElement; ParagraphFormattedElement;
+		import flashx.textLayout.elements.SpanElement; SpanElement;
+		import flashx.textLayout.elements.SpecialCharacterElement; SpecialCharacterElement;
+		import flashx.textLayout.elements.SubParagraphGroupElement; SubParagraphGroupElement;
+		import flashx.textLayout.elements.TabElement; TabElement;
+		import flashx.textLayout.elements.TCYElement; TCYElement;
+		import flashx.textLayout.elements.TextFlow; TextFlow;
+		import flashx.textLayout.elements.TextRange; TextRange;
+		
+		import flashx.textLayout.events.CompositionCompleteEvent; CompositionCompleteEvent;
+		import flashx.textLayout.events.DamageEvent; DamageEvent;
+		import flashx.textLayout.events.FlowElementMouseEvent; FlowElementMouseEvent;
+		import flashx.textLayout.events.ModelChange; ModelChange;
+		import flashx.textLayout.events.StatusChangeEvent; StatusChangeEvent;
+		import flashx.textLayout.events.TextLayoutEvent; TextLayoutEvent;
+		
+		import flashx.textLayout.factory.TextLineFactoryBase; TextLineFactoryBase;
+		import flashx.textLayout.factory.StringTextLineFactory; StringTextLineFactory;
+		import flashx.textLayout.factory.TextFlowTextLineFactory; TextFlowTextLineFactory;
+		import flashx.textLayout.factory.TruncationOptions; TruncationOptions;		
+
+		import flashx.textLayout.formats.BaselineOffset; BaselineOffset;
+		import flashx.textLayout.formats.BaselineShift; BaselineShift;
+		import flashx.textLayout.formats.BlockProgression; BlockProgression;
+
+		import flashx.textLayout.formats.Category; Category;
+		import flashx.textLayout.formats.Direction; Direction;
+		import flashx.textLayout.formats.Float; Float;
+		import flashx.textLayout.formats.FlowElementDisplayType; FlowElementDisplayType;
+		import flashx.textLayout.formats.FormatValue; FormatValue;
+		import flashx.textLayout.formats.IMEStatus; IMEStatus;
+		import flashx.textLayout.formats.ITextLayoutFormat; ITextLayoutFormat;
+		import flashx.textLayout.formats.ITabStopFormat; ITabStopFormat;
+		import flashx.textLayout.formats.JustificationRule; JustificationRule;
+		import flashx.textLayout.formats.LeadingModel; LeadingModel;
+		import flashx.textLayout.formats.LineBreak; LineBreak;
+		import flashx.textLayout.formats.TabStopFormat; TabStopFormat;
+		import flashx.textLayout.formats.TextAlign; TextAlign;
+		import flashx.textLayout.formats.TextDecoration; TextDecoration;
+		import flashx.textLayout.formats.TextJustify; TextJustify;
+		import flashx.textLayout.formats.TextLayoutFormat; TextLayoutFormat;		
+		import flashx.textLayout.formats.TextLayoutFormatValueHolder; TextLayoutFormatValueHolder;		
+		import flashx.textLayout.formats.VerticalAlign; VerticalAlign;
+		import flashx.textLayout.formats.WhiteSpaceCollapse; WhiteSpaceCollapse;
+
+		import flashx.textLayout.property.ArrayProperty; ArrayProperty;
+		import flashx.textLayout.property.BooleanProperty; BooleanProperty;
+		import flashx.textLayout.property.EnumStringProperty; EnumStringProperty;
+		import flashx.textLayout.property.IntProperty; IntProperty;
+		import flashx.textLayout.property.IntWithEnumProperty; IntWithEnumProperty;
+		import flashx.textLayout.property.NumberOrPercentOrEnumProperty; NumberOrPercentOrEnumProperty;
+		import flashx.textLayout.property.NumberOrPercentProperty; NumberOrPercentProperty;
+		import flashx.textLayout.property.NumberProperty; NumberProperty;
+		import flashx.textLayout.property.NumberWithEnumProperty; NumberWithEnumProperty;
+		import flashx.textLayout.property.Property; Property;
+		import flashx.textLayout.property.StringProperty; StringProperty;
+		import flashx.textLayout.property.UintProperty; UintProperty;
+		
+		import flashx.textLayout.utils.CharacterUtil; CharacterUtil;
+		import flashx.textLayout.utils.GeometryUtil; GeometryUtil;
+		
+		// Alphabetical list of classes to be included as part of text_model.swc.
+		// This should mirror what's in the .flexLibProperties
+		
+		CONFIG::release public function exportAssert():void
+		{
+			assert();
+		}
+	}
+}
+
diff --git a/textLayout_core/src/flashx/textLayout/accessibility/TextAccImpl.as b/textLayout_core/src/flashx/textLayout/accessibility/TextAccImpl.as
new file mode 100755
index 0000000..c576e72
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/accessibility/TextAccImpl.as
@@ -0,0 +1,428 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.accessibility
+{
+	import flash.accessibility.Accessibility;
+	import flash.accessibility.AccessibilityImplementation;
+	import flash.accessibility.AccessibilityProperties;
+	import flash.display.DisplayObject;
+	import flash.events.Event;
+	
+	import flashx.textLayout.edit.EditingMode;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+    //TODO this is in text_edit... which violates MVC yet again... what to do?
+    //import flashx.textLayout.events.SelectionEvent;
+    
+	//TODO handle selectable text when FP implements the new selection API:
+	//     http://frpbugapp.macromedia.com/bugapp/detail.asp?id=217540
+	//     To catch the selection changes reliably, listen for SelectionEvent,
+	//     which is dispatched on the TextFlow whenever the selection changes.
+
+    //TODO handle scrolling? might need to expose scrolling in here
+    
+	//TODO handle hyperlinks? I don't know if MSAA has a concept for this
+	//    (what other text advanced features must be accessible? graphics?)
+	//TODO what if there is HTML in it? strip it, or read it? we don't have an
+	//     htmlText property, do we?
+
+    // TODO Do we want to read the contents of each sprite and stop, even if the
+    // text flows into other sprite, meaning we read text in taborder; or do we
+    // want to read the entire model and not worry about the presentation
+    // (simpler)? Not sure if I can get the contents of each sprite separately.
+    
+    // TODO TESTING:
+    //   * Test that JAWS reads when setting the focus programmatically.
+    //   * Tests for changing every part of the model programmatically -- role
+    //     and state should update accordingly, visibility, and text contents.
+    //   * Test that setting tabOrder reads as expected. What happens if you set
+    //     tabOrder on multiple flowComposers?
+    
+    //TODO update this comment after integration
+	/**
+	 * @private
+	 * The TextAccImpl class adds accessibility for text components.
+	 * This hooks into DisplayObjects when TextFlow.container is set.
+	 */
+	public class TextAccImpl extends AccessibilityImplementation
+	{
+	    //TODO might want to put these constants in a new class if they are
+	    //     used anywhere else.
+	    
+		/** Default state */
+		protected static const STATE_SYSTEM_NORMAL:uint = 0x00000000;
+		
+		/** Read-only text */
+		protected static const STATE_SYSTEM_READONLY:uint = 0x00000040;
+		
+		/** Inivisible text */
+		//TODO unused, but supported state for text in MSAA
+		protected static const STATE_SYSTEM_INVISIBLE:uint = 0x00008000;
+		
+		/** Default role -- read-only, unselectable text. */
+		protected static const ROLE_SYSTEM_STATICTEXT:uint = 0x29;
+		
+		/** Editable OR read-only, selectable text. */
+		protected static const ROLE_SYSTEM_TEXT:uint = 0x2a;
+		
+		/* When the name changes (name is the text conent in STATICTEXT). */
+		protected static const EVENT_OBJECT_NAMECHANGE:uint = 0x800c;
+		
+		/* When the value changes (value is the text content in TEXT). */
+		protected static const EVENT_OBJECT_VALUECHANGE:uint = 0x800e;
+	
+		/**
+		 *  A reference to the DisplayObject that is hosting accessible text.
+		 */
+		//TODO for now this assumes only the first DO in a flow is accessible
+		//     in the future each flow DO should host its own accimpl and read
+		//     the text only for its own box.
+		//
+		//     Or... perhaps we use getChildIDArray to manage all the text
+		//     flows if they are linked below some master component (but I don't
+		//     think this is the way it will happen).
+		protected var textContainer:DisplayObject;
+		
+		/**
+		 *  A reference to the TextFlow where our text originates.
+		 */
+		protected var textFlow:TextFlow;
+		
+		/**
+		 *  Constructor.
+		 * 
+		 *  @param textContainer The DisplayObject instance that this
+		 *                       TextAccImpl instance is making accessible.
+		 *  @param textFlow The TextFlow that is hosting the textContainer.
+		 */
+		public function TextAccImpl(textCont:DisplayObject, textFlow:TextFlow)
+		{
+			super();
+	
+			this.textContainer = textCont;
+			this.textFlow = textFlow;
+			
+			// stub is true when you are NOT providing an acc implementation
+			// reports to reader as graphic
+			stub = false;
+			
+			if (textCont.accessibilityProperties == null)
+			{
+    			textCont.accessibilityProperties =
+    			    new AccessibilityProperties();
+			}
+
+            //TODO
+            // setup event listeners for text selection and model changes
+            //textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,
+            //                          eventHandler);
+            textFlow.addEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE, eventHandler);
+		}
+		
+		public function detachListeners():void
+		{
+			textFlow.removeEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE, eventHandler);
+		}
+		
+		/**
+		 *  Returns the system role for the text.
+		 *
+		 *  @param childID uint.
+		 *  @return Role associated with the text.
+		 */
+		override public function get_accRole(childID:uint):uint
+		{
+		    // trace("get_accRole()");
+		    
+		    const iManager:ISelectionManager = textFlow.interactionManager;
+		    if (iManager == null)
+		    {
+		        // non-selectable, non-editable text is STATICTEXT
+		        return ROLE_SYSTEM_STATICTEXT
+		    }
+		    else // iManager is an IEditManager and/or ISelectionManager
+		    {
+		        // read-only selectable or editable selectable text are TEXT
+		        return ROLE_SYSTEM_TEXT;
+		    }
+		}
+		
+		/**
+		 *  Returns the state of the text.
+		 *
+		 *  @param childID uint.
+		 *  @return Role associated with the text.
+		 */
+		override public function get_accState(childID:uint):uint
+		{
+		    // trace("get_accState()");
+		    
+		    const iManager:ISelectionManager = textFlow.interactionManager;
+		    
+		    //TODO handle STATE_SYSTEM_INVISIBLE for all cases below
+		    //     and add an event to detect changes--does Flash support this?
+		    
+		    //TODO handle STATE_SYSTEM_PROTECTED for all cases below
+		    //     if vellum gets a concept of password fields, then it needs to 
+		    //     emit this value if the field is converted to a password;
+		    //     otherwise the Flex framework will need to be sure to emit
+		    //     this state in a text input component.
+		    
+		    // note: focus-related states are handled by the player
+		    
+		    if (iManager == null)
+		    {
+		        // non-selectable, non-editable text
+		        return STATE_SYSTEM_READONLY;
+		    }
+		    // must check IEditManager before ISelectionManager (it can be both)
+		    else if (iManager.editingMode == EditingMode.READ_WRITE)
+		    {
+		        // editable selectable text
+		        return STATE_SYSTEM_NORMAL;
+		    }
+		    else // if (iManager instanceof ISelectionManager)
+		    {
+		        // read-only selectable text
+		        return STATE_SYSTEM_READONLY;
+		    }
+		}
+		
+		/**
+		 *  Returns the name of the text.
+		 *
+		 *  @param childID uint.
+		 *  @return Name of the text.
+		 */
+		override public function get_accName(childID:uint):String
+		{
+		    // trace("get_accName()");
+		    
+		    switch (get_accRole(childID))
+		    {
+    		    case ROLE_SYSTEM_STATICTEXT:
+    		    {
+        		    //TODO this SHOULD come from TextConverter, but then there is a
+        		    //     circular build dependency since importExport builds
+        		    //     against model, and it probably violates mvc
+        			//return TextConverter.export(textFlow,
+        			//                         TextConverter.PLAIN_TEXT_FORMAT);
+        			
+        			//TODO this is probably expensive. is there a way to cache
+        			//      this and know when dirty?
+        			//TODO  look at the generation and determine when it's dirty
+        			return exportToString(textFlow);
+    		    }
+    		    
+		        case ROLE_SYSTEM_TEXT:
+		        default:
+            		return null;
+    		}
+		}
+		
+		/**
+		 *  Returns the value of the text.
+		 *
+		 *  @param childID uint.
+		 *  @return Name of the text.
+		 */
+		override public function get_accValue(childID:uint):String
+		{
+		    // trace("get_accValue()");
+		    
+		    switch (get_accRole(childID))
+		    {
+		        case ROLE_SYSTEM_TEXT:
+    		    {
+        		    //TODO this SHOULD come from TextConverter, but then there is a
+        		    //     circular build dependency since importExport builds
+        		    //     against model, and it probably violates mvc
+        			//return TextConverter.export(textFlow,
+        			//                         TextConverter.PLAIN_TEXT_FORMAT);
+        			
+        			// TODO this is probably expensive. is there a way to cache
+        			//      this and know when dirty?
+        			//TODO  look at the generation and determine when it's dirty
+        			return exportToString(textFlow);
+    		    }
+    		    
+    		    case ROLE_SYSTEM_STATICTEXT:
+		        default:
+            		return null;
+    		}
+		}
+
+		/**
+		 * Handles COMPOSITION_COMPLETE and SELECTION_CHANGE events,
+		 * updates the MSAA model.
+    	 */
+    	protected function eventHandler(event:Event):void
+    	{
+    		switch (event.type)
+    		{
+                // This updates the entire accessibility DOM.
+                // get_accName is probably expensive here, it happens ONLY if
+                // JAWS is running, otherwise Accessibility.* calls are NOOP.
+                //
+                // Event does NOT fire when interactionManager changes; ideally
+                // we'd want to tell MSAA the role changed, but apparently roles
+                // are typically static and that's not a supported workflow.
+                // instead, Flash occasionally polls the displaylist, e.g. when
+                // you mouseover. calling updateProperties() doesn't necessarily
+                // trigger role updates (calls to get_acc*()).
+    			case CompositionCompleteEvent.COMPOSITION_COMPLETE:
+    			{
+    			    // TODO change childID from 0 if we use getChildIDArray
+    			    //      otherwise delete this comment
+	 				try {
+	    				Accessibility.sendEvent(textContainer, 0,
+    					                        EVENT_OBJECT_NAMECHANGE);
+    					Accessibility.sendEvent(textContainer, 0,
+    					                        EVENT_OBJECT_VALUECHANGE);
+    					Accessibility.updateProperties();
+					} catch (e_err:Error) {
+	 					// generic error occurred.
+                        // this can happen in the SA player since there is no
+                        // Accessibility implementation.
+	 				}
+    				break;
+    			}
+    			
+                //TODO when we have the FP selection APIs
+    			// case SelectionEvent.SELECTION_CHANGE:
+    			// {
+                //   // this is just stubbed code, I don't know what *needs* to
+                //   // be done for SELECTION_CHANGE
+    			// 	Accessibility.sendEvent(textContainer, 0,
+    			//                          EVENT_OBJECT_TEXTSELECTIONCHANGED);
+    			// 	Accessibility.updateProperties();
+    			// 	break;
+    			// }
+    		}
+    	}
+		
+		/**
+		 * TODO HACK, remove and refactor.
+		 * 
+		 * This is copied from PlainTextExportFilter, which I would prefer to
+		 * access through TextConverter.export(textFlow,
+		 *                                  TextConverter.PLAIN_TEXT_FORMAT);
+		 * 
+		 * But, PTEF is in importExport, which builds against text_model,
+		 * which is a circular dependency.
+		 * 
+		 * Also, it seems to be adding a trailing newline, which is bad for
+		 * accessibility unless it is really there.
+		 * 
+		 * Might want to export and strip out hyphens.
+		 * Move it to the model?
+		 */
+		private static function exportToString(source:TextFlow):String
+		{
+			var leaf:FlowLeafElement = source.getFirstLeaf();
+			var rslt:String = "";
+			var curString:String = "";
+			var discretionaryHyphen:String = String.fromCharCode(0x00AD);
+			while (leaf)
+			{
+            	var p:ParagraphElement = leaf.getParagraph();
+            	while (true)
+            	{
+            		curString = leaf.text;
+            		
+            		//split out discretionary hyphen and put string back together
+					var temparray:Array = curString.split(discretionaryHyphen);
+					curString = temparray.join("");
+					
+	               	rslt += curString;
+					leaf = leaf.getNextLeaf(p);
+					if (!leaf)
+                    {
+                        // we want newlines between paragraphs but not at the end
+                    	rslt += "\n";
+						break;
+					}
+            	}
+            	leaf = p.getLastLeaf().getNextLeaf();
+   			}
+   			return rslt;
+		}
+		
+		/** 
+		 * The zero-based character index value of the first character in the current selection.
+		 * Components which wish to support inline IME or Accessibility should call into this method.
+		 *
+		 * @return the index of the character at the anchor end of the selection, or <code>-1</code> if no text is selected.
+		 * 
+		 * @playerversion Flash 10.0
+		 * @langversion 3.0
+		 */
+		public function get selectionActiveIndex():int
+		{
+			var selMgr:ISelectionManager = textFlow.interactionManager;
+			var selIndex:int = -1;
+			if(selMgr && selMgr.editingMode != EditingMode.READ_ONLY)
+			{
+				selIndex = selMgr.activePosition;
+			}
+			
+			return selIndex;
+		}
+		
+		/** 
+		 * The zero-based character index value of the last character in the current selection.
+		 * Components which wish to support inline IME or Accessibility should call into this method.
+		 *
+		 * @return the index of the character at the active end of the selection, or <code>-1</code> if no text is selected.
+		 * 
+		 * @playerversion Flash 10.0
+		 * @langversion 3.0
+		 */
+		public function get selectionAnchorIndex():int
+		{
+			var selMgr:ISelectionManager = textFlow.interactionManager;
+			var selIndex:int = -1;
+			if(selMgr && selMgr.editingMode != EditingMode.READ_ONLY)
+			{
+				selIndex = selMgr.anchorPosition;
+			}
+			
+			return selIndex;
+		}
+		
+		/** Enable search index for Ichabod
+		 * Returns the entire text of the TextFlow, or null if search index is not enabled
+		 * @see GlobalSettings.searchIndexEnabled
+		 */
+		public function get searchText():String
+		{
+			return GlobalSettings.enableSearch ? textFlow.getText() : null;
+		}
+		
+	}
+}
+
diff --git a/textLayout_core/src/flashx/textLayout/compose/BaseCompose.as b/textLayout_core/src/flashx/textLayout/compose/BaseCompose.as
new file mode 100755
index 0000000..3dc4060
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/BaseCompose.as
@@ -0,0 +1,1287 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBaseline;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.*;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.*;
+	import flashx.textLayout.formats.*;
+	import flashx.textLayout.utils.LocaleUtil;
+	
+	use namespace tlf_internal;
+	
+	
+	[ExcludeClass]
+	/** @private Common composer base class */
+	public class BaseCompose
+	{
+		
+		public static function get globalSWFContext():ISWFContext
+		{ 
+			return GlobalSWFContext.globalSWFContext; 
+		}
+		
+		protected var _parcelList:IParcelList;
+		
+		/** List of areas we're composing into, matches the container's bounding box */
+		public function get parcelList():IParcelList
+		{ return _parcelList; }
+		
+		/** Element of current location */
+		protected var _curElement:FlowLeafElement;		
+		/** Absolute start position of _curElement */
+		protected var _curElementStart:int;		
+		/** Offset from element start to current location */
+		protected var _curElementOffset:int;		
+		/** ParagraphElement that contains the current location */
+		protected var _curParaElement:ParagraphElement;	
+		protected var _curParaFormat:ITextLayoutFormat;
+		/** Absolute start position of _curParaElement */
+		protected var _curParaStart:int;
+		/** leading direction for the current line's para (set when line is being composed and committed to _lastLineLeadingModel when line is finalized) */
+		private var _curLineLeadingModel:String = "";
+		/** leading amount for the current line (set when line is being composed and committed to _lastLineLeading when line is finalized) */
+		private var _curLineLeading:Number;
+		/** leading direction for the last line's para */
+		protected var _lastLineLeadingModel:String = "";
+		/** leading amount for the last line */
+		protected var _lastLineLeading:Number;
+		/** descent of the last line */
+		protected var _lastLineDescent:Number;
+		/** Amount of spaceAfter added to the previous line */
+		protected var _spaceCarried:Number;
+		/** BlockProgression - vertical horizontal etc. @see text.formats.BlockProgression */
+		protected var _blockProgression:String;
+		
+		/** Minimum left edge coordinate across all the parcels in a controller */
+		private var _controllerLeft:Number;
+		/** Minimum top edge across all the parcels in a controller */
+		private var _controllerTop:Number;
+		/** Maximum right edge coordinate across all the parcels in a controller */
+		private var _controllerRight:Number;
+		/** Maximum bottom edge coordinate across all the parcels in a controller */
+		private var _controllerBottom:Number;
+		
+		/** Maximum horizontal extension from left/right edge of the parcel.  Alignment width for the parcel. */
+		protected var _contentLogicalExtent:Number;
+		/* Commited extent any lines needing additional alignment must update this number */
+		protected var _contentCommittedExtent:Number;
+		
+		/** Minimum left edge coordinate across all the parcels in a controller */
+		protected var _parcelLeft:Number;
+		/** Minimum top edge across all the parcels in a controller */
+		protected var _parcelTop:Number;
+		/** Maximum right edge coordinate across all the parcels in a controller */
+		protected var _parcelRight:Number;
+		/** Maximum bottom edge coordinate across all the parcels in a controller */
+		protected var _parcelBottom:Number;
+		
+		/** owning textFlow of current compose */
+		protected var _textFlow:TextFlow;
+		private var _releaseLineCreationData:Boolean;
+		/** flowComposer of current compose */
+		protected var _flowComposer:StandardFlowComposer;
+		/** rootElement of current compose */
+		protected var _rootElement:ContainerFormattedElement;
+		/** position to stop composing at */
+		protected var _stopComposePos:int;
+		
+		/** First damaged controller to begin composing */
+		protected var _startController:ContainerController;
+		/** Beginning composition position.  Note this gets cleared once its been passed */
+		protected var _startComposePosition:int;
+		
+		
+		// scratch line slugs
+		static protected var _candidateLineSlug:Rectangle = new Rectangle();
+		static protected var _lineSlug:Rectangle = new Rectangle();
+		
+		// scratch array for holding lines awaiting alignment
+		static private var _alignLines:Array;
+		
+		/** Parcel we are composing - used for keeping track of when it changes b/c parcelList.parcel may have advanced */
+		protected var _curParcel:Parcel;
+		
+		/** Start position of _curParcel */
+		protected var _curParcelStart:int;
+		
+		/** Constructor. */
+		public function  BaseCompose()
+		{	
+			
+		}
+		
+		protected function createParcelList():IParcelList
+		{ return null; }
+		protected function releaseParcelList(list:IParcelList):void
+		{ }
+		
+		/** Starting controller for skipping ahead */
+		public function get startController():ContainerController
+		{ return _startController; }
+		
+		/** prevent any leaks. @private */
+		tlf_internal function releaseAnyReferences():void
+		{
+			_curElement = null;
+			_curParaElement = null;
+			_curParaFormat = null;
+			_flowComposer = null;
+			_parcelList = null;
+			_rootElement = null;
+			_startController = null;
+			_textFlow = null;
+		}
+		
+		/** Initialize for a composition that will compose up through the controllerEndIndex, or all the way to the end of the flow
+		 * @param composer
+		 * @param composeToPosition 	-1 means not specified.  0 means request to compose nothing, >0 specifies a position to force compose to
+		 * @param controllerEndIndex	index of the last controller to compose for, or -1 to compose through all controllers
+		 */
+		protected function  initializeForComposer(composer:IFlowComposer, composeToPosition:int, controllerEndIndex:int):void
+		{
+			_parcelList = createParcelList();
+			_parcelList.notifyOnParcelChange = parcelHasChanged;
+			
+			_spaceCarried = 0;
+			// TODO: just use the rootElement for table cells
+			_blockProgression = composer.rootElement.computedFormat.blockProgression;
+			// for a non-specified compose position the ParcelList handles the bail out - just set to textLength
+			_stopComposePos = composeToPosition >= 0 ? Math.min(_textFlow.textLength,composeToPosition) : _textFlow.textLength;
+			
+			// this chains through the list - tell it if a "care about" comopseToPosition was specified
+			_parcelList.beginCompose(composer, controllerEndIndex, composeToPosition > 0);	
+			
+			_contentLogicalExtent = 0;
+			_contentCommittedExtent = 0;
+		}
+		
+		/*
+		* Compose an inline-block element, used for tables or other inline-blocks. The
+		* element has a container associated with it, and the container is going to be placed
+		* after the current paragraph if it fits in the text container.
+		* 
+		* @param composeFrame	the text container we're composing into
+		*/
+		protected function composeFloat(elem:ContainerFormattedElement,composeFrame:ContainerController):void
+		{
+			// Should get handled in derived class
+			CONFIG::debug { assert(false, "Floats are not supported in ComposeState"); }
+		}
+		
+		/** Called when we are about to compose a line. Handler for derived classes to override default behavior. */
+		protected function startLine():void
+		{
+			// does nothing
+		}
+		
+		/** Called when we are finished composing a line. Handler for derived classes to override default behavior.  */
+		protected function endLine():void
+		{
+			// does nothing
+		}		
+		
+		private function composeBlockElement(elem:FlowGroupElement,absStart:int):Boolean
+		{	
+			// Compose all the children, until all the containers are filled, or if we're on the last container, we've hit the stop compose text index
+			var idx:int;
+			if (_startComposePosition != 0)
+			{
+				idx = elem.findChildIndexAtPosition(_startComposePosition-absStart);
+				CONFIG::debug { assert(idx != -1,"Bad _startComposePosition to index in composeBlockElement"); }
+				absStart += elem.getChildAt(idx).parentRelativeStart;
+			}
+			else
+				idx = 0;
+			
+			for (; idx < elem.numChildren && (absStart <= _stopComposePos || ! parcelList.atLast()); idx++)
+			{
+				var child:FlowElement = elem.getChildAt(idx);
+				
+				var para:ParagraphElement = child as ParagraphElement;
+				if (para)
+				{
+					var rslt:Boolean = composeParagraphElement(para,absStart);
+					// we need to flush each TextBlock - this saves a lot of memory at the cost of performance during editing	
+					// note that this is a nop on older players.  only newer players implement flush	
+					if (releaseLineCreationData)
+						para.releaseLineCreationData();
+					if (!rslt)
+						return false;	// done
+				}
+				else if (child.display == FlowElementDisplayType.FLOAT)
+				{
+					composeFloat(ContainerFormattedElement(child),_parcelList.controller);
+					if (_parcelList.atEnd())
+						return false;
+					CONFIG::debug { assert(child.getAbsoluteStart() + child.textLength - _parcelList.controller.absoluteStart >= 0, "frame has negative composition"); }
+				}
+				else 
+				{
+					if (!composeBlockElement(FlowGroupElement(child),absStart))
+						return false;
+				}
+				
+				absStart += child.textLength;
+			}
+			return true;
+		}
+		
+		// TODO: move somewhere reasonable
+		
+		private static function doNothingOnParcelChange(newParcel:Parcel):void
+		{ }
+		
+		
+		/**
+		 * Compose the flow into the text container. Starts at the root element,
+		 * and composes elements until either there are no more elements, or the
+		 * text container is full. It will compose only the lines which are
+		 * marked invalid, so that existing lines that are unchanged are not
+		 * recomposed.
+		 */
+		public function composeTextFlow(textFlow:TextFlow, composeToPosition:int, controllerEndIndex:int):int
+		{
+			_textFlow = textFlow;
+			_releaseLineCreationData = textFlow.configuration.releaseLineCreationData && Configuration.playerEnablesArgoFeatures;
+			
+			// must setup _startController and _startComposePosition
+			initializeForComposer(textFlow.flowComposer, composeToPosition, controllerEndIndex);
+			
+			_flowComposer = _textFlow.flowComposer as StandardFlowComposer;
+			_rootElement = textFlow;
+			_curElementOffset = 0;
+			_curElement = _rootElement.getFirstLeaf();	
+			
+			_curElementStart = 0;		// current position in the text (start of current line)
+			
+			_curParcel = null;
+			resetControllerBounds();
+			
+			if (_startController != _flowComposer.getControllerAt(0))
+			{
+				var cacheNotify:Function = _parcelList.notifyOnParcelChange;
+				_parcelList.notifyOnParcelChange =  doNothingOnParcelChange;
+				// skip parcels until the first one in startController
+				while(_parcelList.currentParcel.controller != _startController)
+					_parcelList.next();
+				_parcelList.notifyOnParcelChange =  cacheNotify;
+			}
+			
+			parcelHasChanged(_parcelList.currentParcel);		// force start of composition acccounting initialization
+			
+			composeInternal(_rootElement,0);
+			
+			for (;;)
+			{
+				if (parcelList.atEnd())
+				{
+					parcelHasChanged(null);		// force end of composition accounting for the parcel
+					break;
+				}				
+				parcelList.next();
+			}
+			
+			
+			releaseParcelList(_parcelList);
+			_parcelList = null;
+			
+			return _curElementStart + _curElementOffset;		// Return last composed position
+		}
+		
+		private function resetControllerBounds():void
+		{
+			_controllerLeft = TextLine.MAX_LINE_WIDTH;
+			_controllerTop = TextLine.MAX_LINE_WIDTH;
+			_controllerRight = -TextLine.MAX_LINE_WIDTH;
+			_controllerBottom = -TextLine.MAX_LINE_WIDTH;
+		}
+		
+		/** Release line creation data during this compose */
+		protected function get releaseLineCreationData():Boolean
+		{ return _releaseLineCreationData; }
+		
+		// Create new lines through composition. lines, wrap, etc.
+		protected function composeInternal(composeRoot:FlowGroupElement,absStart:int):void
+		{
+			composeBlockElement(composeRoot,absStart);
+		}
+		
+		protected function composeParagraphElement(elem:ParagraphElement,absStart:int):Boolean
+		{
+			CONFIG::debug { assert(false,"MISSING OVERRIDE"); }
+			return false;
+		}
+		
+		protected function composeParagraphElementIntoLines():Boolean
+		{
+			var curLine:TextFlowLine;
+			
+			// loop creating lines
+			for (;;)
+			{
+				if (_parcelList.atEnd())
+					return false;
+				
+				// Allow derived classes to do processing here
+				startLine();
+				
+				// Get the next line
+				curLine = composeNextLine();
+				if (curLine ==  null)
+					return false;
+				
+				var alignData:AlignData = calculateTextAlign(curLine, curLine.getTextLine());
+				
+				/* {
+				for (var idx:int = 0; idx < curLine.textLine.atomCount; idx++)
+				{
+				trace(idx.toString()+": beginIndex: " + curLine.textLine.getAtomTextBlockBeginIndex(idx)+ " bidiLevel: "+ curLine.textLine.getAtomBidiLevel(idx) + " bounds: " + curLine.textLine.getAtomBounds(idx));
+				}
+				} */
+				
+				if ((curLine.spaceBefore != 0 || _spaceCarried != 0) && !_parcelList.isColumnStart())
+					_parcelList.addTotalDepth(Math.max(curLine.spaceBefore, _spaceCarried));
+				_spaceCarried = 0;
+				_parcelList.addTotalDepth(curLine.height);
+				_curElementOffset += curLine.textLength;
+				// textLength is the first character in the next line
+				
+				var textLine:TextLine = curLine.getTextLine();
+				
+				var lineWidth:Number; 
+				if (_parcelList.explicitLineBreaks)
+				{
+					var isRTL:Boolean = _curParaElement.computedFormat.direction == Direction.RTL;
+					textLine = curLine.getTextLine(true);
+					var lastAtom:int = textLine.atomCount - 1;
+					// If we're at the end of the paragraph, don't count the terminator
+					var endOfParagraph:Boolean = _curElementStart+_curElementOffset == _curParaStart + _curParaElement.textLength;
+					if (endOfParagraph && !isRTL)
+						--lastAtom;	// can go negative if just the terminator.  in that case use left/top of atom zero
+					var bounds:Rectangle = textLine.getAtomBounds(lastAtom >= 0 ? lastAtom : 0);	// get rightmost atom bounds
+					lineWidth = (_blockProgression == BlockProgression.TB) 
+						? (lastAtom >= 0 ? bounds.right : bounds.left)
+						: (lastAtom >= 0 ? bounds.bottom : bounds.top);
+					if (isRTL)	// in right to left, get leftmost atom bounds, that has trailing space
+					{
+						// in RTL strip the width of the paragraph terminator from the front
+						bounds = textLine.getAtomBounds(lastAtom != 0 && endOfParagraph ? 1 : 0);						
+						lineWidth -= (_blockProgression == BlockProgression.TB) ? bounds.left : bounds.top;
+					}
+					textLine.flushAtomData();
+				}
+				else
+					lineWidth = textLine.textWidth;
+				
+				var rightSidePadding:Number =  _curParaFormat.direction == Direction.LTR ? _curParaFormat.paragraphEndIndent : _curParaFormat.paragraphStartIndent;
+				var textIndent:Number = 0;
+				var rightSideIndent:Number = 0;
+				var leftSideIndent:Number = 0;
+				if (_curParaFormat.direction == Direction.RTL && (curLine.location & TextFlowLineLocation.FIRST))
+				{
+					// the textIndent isn't applied on left aligned paragraphs in measured RTL mode
+					// need to be careful because leftaligned paragraphs need to be exactly right coming out of this routine
+					if (alignData && (_blockProgression == BlockProgression.TB && !curLine.controller.measureWidth || _blockProgression == BlockProgression.RL && !curLine.controller.measureHeight))
+						rightSideIndent = _curParaFormat.textIndent;
+				}
+				var leftSidePadding:Number =  _curParaFormat.direction == Direction.LTR ? _curParaFormat.paragraphStartIndent : _curParaFormat.paragraphEndIndent;
+				if (_curParaFormat.direction == Direction.LTR && (curLine.location & TextFlowLineLocation.FIRST))
+				{
+					// recording leftSideIndent is here because there is an extra alignment step for non-left aligned paragraphs
+					leftSideIndent = _curParaFormat.textIndent;
+				}					
+				
+				if (alignData)
+				{
+					alignData.rightSidePadding = rightSidePadding;
+					alignData.leftSidePadding  = leftSidePadding;
+					alignData.lineWidth = lineWidth;
+					alignData.rightSideIndent = rightSideIndent;
+					alignData.leftSideIndent = leftSideIndent;
+					
+					// trace("AlignData",alignData.leftSidePadding,alignData.rightSidePadding,alignData.lineWidth,alignData.leftSideIndent,alignData.rightSideIndent);
+				}
+				
+				// extent from the left margin
+				var lineExtent:Number = lineWidth + leftSidePadding+leftSideIndent + rightSidePadding+rightSideIndent;
+				_contentLogicalExtent = Math.max(_contentLogicalExtent, lineExtent);
+				if (!alignData)
+					_contentCommittedExtent = Math.max(_contentCommittedExtent, lineExtent);
+				
+				CONFIG::debug { assert(_parcelList.controller.textLength >= 0, "frame has negative composition"); }
+				
+				if (_parcelList.atEnd())
+					return false;
+				
+				endLine();
+				
+				// advance to the next element, using the rootElement of the container as a limitNode
+				// to prevent going past the content bound to this container
+				if (_curElementOffset >= _curElement.textLength)
+				{
+					// We may have composed ahead over several spans; skip until we match up
+					// Loop until we use catch up to where the line we just composed ended (pos).
+					// Stop if we run out of elements. Skip empty inline elements, and skip floats
+					// that came at the start of the line before any text -- they've already been 
+					// processed.
+					do{
+						_curElementOffset -= _curElement.textLength;
+						_curElementStart  += _curElement.textLength;
+						if (_curElementStart == _curParaStart+_curParaElement.textLength)
+						{
+							_curElement = null;
+							break;
+						}
+						_curElement = _curElement.getNextLeaf();
+						CONFIG::debug { assert(_curElement && _curElement.getParagraph() == _curParaElement,"composeParagraphElement: bad textLength in TextLine"); }
+					} while (_curElementOffset >= _curElement.textLength || _curElement.textLength == 0 );
+				}
+				
+				_spaceCarried = curLine.spaceAfter;
+				
+				
+				if (_curElement == null)
+					break;
+			}
+			return true;
+		}
+		
+		protected function composeNextLine():TextFlowLine
+		{
+			CONFIG::debug { throw new Error("composeNextLine requires override"); }		
+			return null;
+		}
+		
+		// fills in _lineSlug
+		protected function fitLineToParcel(curLine:TextFlowLine, isNewLine:Boolean):TextFlowLine
+		{
+			// Try to place the line in the current parcel.
+			// get a zero height parcel. place the line there and then test if it still fits.
+			// if it doesn't place it in the new result parcel
+			// still need to investigate because the height used on the 2nd getLineSlug call may be too big.
+			for (;;)
+			{
+				if (_parcelList.getLineSlug(_candidateLineSlug,0))
+					break;
+				_parcelList.next();
+				if (_parcelList.atEnd())
+					return null;
+				_spaceCarried = 0;
+			}
+			
+			curLine.setController(_parcelList.controller,_parcelList.columnIndex);
+			
+			// If we are at the last parcel, we let text be clipped if that's specified in the configuration. At the point where no part of text can be accommodated, we go overset.
+			// If we are not at the last parcel, we let text flow to the next parcel instead of getting clipped.
+			var spaceBefore:Number = Math.max(curLine.spaceBefore, _spaceCarried);
+			for (;;)
+			{
+				finishComposeLine(curLine, _candidateLineSlug, isNewLine);	
+				if (_parcelList.getLineSlug(_lineSlug, spaceBefore + (_parcelList.atLast() && _textFlow.configuration.overflowPolicy != OverflowPolicy.FIT_DESCENDERS ? curLine.height-curLine.ascent : curLine.height+curLine.descent)))
+				{
+					CONFIG::debug { assert(_parcelList.getComposeXCoord(_candidateLineSlug) == _parcelList.getComposeXCoord(_lineSlug) && _parcelList.getComposeYCoord(_candidateLineSlug) == _parcelList.getComposeYCoord(_lineSlug),"fitLineToParcel: slug mismatch"); }
+					break;
+				}
+				spaceBefore = curLine.spaceBefore;
+				for (;;)
+				{
+					_parcelList.next();
+					if (_parcelList.atEnd())
+						return null;
+					if (_parcelList.getLineSlug(_candidateLineSlug,0))
+						break;
+				}
+				curLine.setController(_parcelList.controller,_parcelList.columnIndex);
+			}						
+			
+			// check to see if we got a good line
+			return (_parcelList.getComposeWidth(_lineSlug) == curLine.outerTargetWidth) ? curLine : null;
+		}
+		
+		
+		protected function finishComposeLine(curLine:TextFlowLine, lineSlug:Rectangle, isNewLine:Boolean):void
+		{      	
+			var curTextLine:TextLine = curLine.getTextLine();
+			var lineHeight:Number = 0;
+			//replace X and Y with rise and run.  
+			//	rise - the offset within a line relative to block progressiong.  For RL this is X, for TB Y
+			//	run - the indentation of the line.  For RL this is Y, TB X
+			var rise:Number = _blockProgression != BlockProgression.RL ? parcelList.getComposeYCoord(lineSlug) : _parcelList.getComposeXCoord(lineSlug);
+			var run:Number = _blockProgression != BlockProgression.RL ? parcelList.getComposeXCoord(lineSlug) : _parcelList.getComposeYCoord(lineSlug);
+			
+			if (_curParaFormat.direction == Direction.LTR)
+			{
+				run += curLine.lineOffset;
+			} 
+			else 
+			{
+				run += curLine.outerTargetWidth-curLine.lineOffset-curLine.targetWidth;
+				
+				if (curLine.outerTargetWidth == TextLine.MAX_LINE_WIDTH && curLine.location&TextFlowLineLocation.FIRST)	// doing measurement ignore 
+				{
+					run += curLine.paragraph.computedFormat.textIndent;
+				}
+			}
+			
+			_curLineLeading = curLine.getLineLeading(_blockProgression,_curElement,_curElementStart);
+			_curLineLeadingModel = _curParaElement.getEffectiveLeadingModel();
+			
+			var containerAttrs:ITextLayoutFormat = _parcelList.controller.computedFormat;		
+			var baselineType:Object = BaselineOffset.LINE_HEIGHT;
+			if (_parcelList.isColumnStart())
+			{
+				// If we're at the top of the column, we need to check the container properties to see
+				// what the firstBaselineOffset should be. This tells us how to treat the line.
+				// However, when vertical alignment is center or bottom, ignore the firstBaselineOffset setting
+				// and treat them as the BaselineOffset.AUTO case
+				if (containerAttrs.firstBaselineOffset != BaselineOffset.AUTO && containerAttrs.verticalAlign != VerticalAlign.BOTTOM && containerAttrs.verticalAlign != VerticalAlign.MIDDLE) 
+				{
+					baselineType = containerAttrs.firstBaselineOffset;
+					// The first line's offset is specified relative firstBaselineOffsetBasis, which used to be, but no longer is, a container-level property
+					// Now it is implicitly deduced based on the container-level locale in the following manner: 
+					// IDEOGRAPHIC_BOTTOM for ja and zh locales (this is the same locale set for which the default LeadingModel is IDEOGRAPHIC_TOP_DOWN)
+					// ROMAN for all other locales
+					var firstBaselineOffsetBasis:String = LocaleUtil.leadingModel(containerAttrs.locale) == LeadingModel.IDEOGRAPHIC_TOP_DOWN ?  flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM : flash.text.engine.TextBaseline.ROMAN;
+					lineHeight -= curTextLine.getBaselinePosition(firstBaselineOffsetBasis);		
+				}
+				else
+				{
+					if (_curLineLeadingModel == LeadingModel.APPROXIMATE_TEXT_FIELD)
+					{
+						// Reinterpret AUTO when APPROXIMATE_TEXT_FIELD leading model is used. 
+						// Align the "enhanced ascent" (an approximation of TextField's notion of ascent baseline, 
+						// which differs from FTEs notion of the same by an amount equal to the line's descent) with the container top inset
+						lineHeight += Math.round(curTextLine.descent) + Math.round(curTextLine.ascent)
+						
+						// Ensure Roman baseline will fall at an integer position. This is desirable for all leading models, 
+						// but only APPROXIMATE_TEXT_FIELD requires it now. In a future release, this code can be moved below and lineX/lineY rounded off directly. 
+						if (_blockProgression == BlockProgression.TB)
+							lineHeight = Math.round(rise + lineHeight) - rise;
+						else
+							lineHeight = rise - Math.round(rise - lineHeight);
+						
+						baselineType = 0; // No further adjustments    
+					}
+					else
+					{
+						// The AUTO case requires aligning line top to container top inset. This efect can be achieved by using firstBaselineOffset=ASCENT
+						// and firstBaselineOffsetBasis=ROMAN 
+						baselineType = BaselineOffset.ASCENT;
+						
+						if(curTextLine.hasGraphicElement)
+						{
+							var firstLineAdjustment:LeadingAdjustment = getLineAdjustmentForInline(curLine, _curLineLeadingModel, true);
+							if(firstLineAdjustment != null)
+							{
+								if(_blockProgression == BlockProgression.RL)
+								{
+									firstLineAdjustment.rise = -(firstLineAdjustment.rise);
+								}
+								_curLineLeading += firstLineAdjustment.leading;
+								rise += firstLineAdjustment.rise;
+							}
+						}
+						
+						lineHeight -= curTextLine.getBaselinePosition(flash.text.engine.TextBaseline.ROMAN);
+					}
+				}
+			}
+			else
+			{
+				// handle space before by adjusting y position of line
+				if (curLine.spaceBefore != 0 || _spaceCarried != 0)
+				{
+					var spaceAdjust:Number = Math.max(curLine.spaceBefore, _spaceCarried);
+					
+					rise += _blockProgression == BlockProgression.RL ? -spaceAdjust :spaceAdjust;
+				}
+			}
+			//getTextLineTypographicAscent
+			if (baselineType == BaselineOffset.ASCENT)
+			{
+				//	CONFIG::debug { assert(_curElement == _textFlow.findLeaf(curLine.absoluteStart),"Bad _curElement"); }
+				CONFIG::debug { assert(_curElementStart == _textFlow.findLeaf(curLine.absoluteStart).getAbsoluteStart(), "Bad _curElementStart"); }
+				lineHeight += curLine.getLineTypographicAscent(_curElement,_curElementStart);
+			}
+			else 
+			{
+				if (baselineType == BaselineOffset.LINE_HEIGHT)
+				{
+					if (_curLineLeadingModel == LeadingModel.APPROXIMATE_TEXT_FIELD)
+					{
+						// Position the "enhanced ascent" (see above) at a distance of leading from the previous line's descent
+						lineHeight += Math.round(_lastLineDescent) + Math.round(curTextLine.ascent) + Math.round(curTextLine.descent) + Math.round(_curLineLeading);
+					}
+					else if (_curLineLeadingModel == LeadingModel.ASCENT_DESCENT_UP)
+					{
+						lineHeight += _lastLineDescent + curTextLine.ascent + _curLineLeading;
+					} 
+					else
+					{
+						// Leading direction is irrelevant for the first line. Treat it as (UP, UP)
+						// TODO-9/3/2008-It may be better to handle Middle/Last lines separately because we know that the previous line also belongs in the same para 
+						var curLeadingDirectionUp:Boolean = _parcelList.isColumnStart() ? true : ParagraphElement.useUpLeadingDirection(_curLineLeadingModel);
+						
+						var prevLeadingDirectionUp:Boolean = _parcelList.isColumnStart() || _lastLineLeadingModel == "" ? true : 
+							ParagraphElement.useUpLeadingDirection(_lastLineLeadingModel);
+						
+						var prevLineFirstElement:FlowLeafElement;
+						
+						if (curLeadingDirectionUp)
+						{	
+							//TODO-9/12/2008-The above behavior is the InDesign behavior but raises some questions about selection shapes.
+							//Should selection code associate leading with the influencing line? That would be weird. InDesign only
+							//supports alternate leading directions in the J feature set, where leading is never included in selection,
+							//so this question does not arise. We take the unambiguous route: ignore leading DOWN at the end of a para
+							lineHeight += _curLineLeading;
+						}
+						else
+						{
+							if (!prevLeadingDirectionUp)
+							{
+								// Same leading directions; use previous line's leading setting.
+								lineHeight += _lastLineLeading;
+							}
+							else
+							{
+								// Make NO leading adjustments. Set lines solid.
+								lineHeight += _lastLineDescent + curTextLine.ascent;
+							}
+						}	
+					}
+				}
+				else
+					lineHeight += Number(baselineType);		// fixed offset
+			}
+			
+			//don't know why, but ascent only needs to be removed from horizontal text.  Hmm, that seems
+			//odd to me - gak 12.15.09
+			rise += _blockProgression == BlockProgression.RL ? -(lineHeight) : lineHeight - curTextLine.ascent;
+			
+			//baselineType will be BaselineOffset.ASCENT for fixed leading
+			if(curTextLine.hasGraphicElement && baselineType != BaselineOffset.ASCENT)
+			{
+				var adjustment:LeadingAdjustment = getLineAdjustmentForInline(curLine, _curLineLeadingModel, false);
+				if(adjustment != null)
+				{	
+					if(_blockProgression == BlockProgression.RL)
+					{
+						adjustment.rise = -(adjustment.rise);
+					}
+					_curLineLeading += adjustment.leading;
+					rise += adjustment.rise;
+				}
+			}
+			
+			
+			if(_blockProgression == BlockProgression.TB)
+				curLine.setXYAndHeight(run,rise,lineHeight);
+			else
+				curLine.setXYAndHeight(rise,run,lineHeight);
+			
+			if(isNewLine)
+				curLine.createAdornments(_blockProgression,_curElement,_curElementStart);
+		}	
+		
+		// Calculate the text alignment of the current line we're composing. If alignment is required, the adjustment will be made in
+		// applyTextAlign, after we've calculated the width of the parcel (it may be based on measurement).
+		// TODO: optimization possibility - do the alignment here when not doing measurement
+		private function calculateTextAlign(curLine:TextFlowLine, curTextLine:TextLine):AlignData
+		{
+			// Adjust the coordinates of the line for center/right.  The line is always left aligned.  TextBlock handles justified cases
+			// If we're on the last line of a justified paragraph, use the textAlignLast value 
+			var textAlignment:String = _curParaFormat.textAlign;
+			if (textAlignment == TextAlign.JUSTIFY && _curParaFormat.textAlignLast != null)
+			{
+				var location:int = curLine.location;
+				if (location == TextFlowLineLocation.LAST || location == TextFlowLineLocation.ONLY)
+					textAlignment = _curParaFormat.textAlignLast;
+			}
+			switch(textAlignment)
+			{
+				case TextAlign.START:
+					textAlignment = (_curParaFormat.direction == Direction.LTR) ? TextAlign.LEFT : TextAlign.RIGHT;
+					break;
+				case TextAlign.END:
+					textAlignment = (_curParaFormat.direction == Direction.LTR) ? TextAlign.RIGHT : TextAlign.LEFT;
+					break; 
+			}
+			
+			var createAlignData:Boolean = textAlignment == TextAlign.CENTER || textAlignment == TextAlign.RIGHT;
+			
+			// in argo lines that have tabs must be either START or JUSTIFY
+			if (Configuration.playerEnablesArgoFeatures)
+			{
+				if (curTextLine["hasTabs"])
+				{
+					if (_curParaFormat.direction == Direction.LTR)
+					{
+						createAlignData = false;	// don't align it - let it be left align
+					}
+					else
+					{
+						createAlignData = true;
+						textAlignment = TextAlign.RIGHT;
+					}
+				}
+			}
+			
+			
+			if (createAlignData)
+			{
+				var alignData:AlignData = new AlignData();
+				alignData.textLine = curTextLine;
+				alignData.center = (textAlignment == TextAlign.CENTER);
+				if (!_alignLines)
+					_alignLines = [];
+				_alignLines.push(alignData);
+				return alignData;
+			}
+			return null;
+		}
+		
+		private function applyTextAlign(effectiveParcelWidth:Number):void
+		{
+			var textLine:TextLine;
+			var line:TextFlowLine;
+			var alignData:AlignData;
+			
+			var coord:Number;
+			var delta:Number;
+			var adjustedLogicalRight:Number;
+			var extraSpace:Number;
+			var leftSideGap:Number;
+			var rightSideGap:Number;
+			
+			if (_blockProgression == BlockProgression.TB)
+			{
+				for each (alignData in _alignLines) 
+				{
+					textLine = alignData.textLine;
+					
+					rightSideGap = alignData.rightSidePadding;
+					leftSideGap = alignData.leftSidePadding;
+					leftSideGap += alignData.leftSideIndent;
+					rightSideGap += alignData.rightSideIndent;
+					
+					line = textLine.userData as TextFlowLine;
+					extraSpace = effectiveParcelWidth - leftSideGap - rightSideGap -  textLine.textWidth;
+					delta = leftSideGap + (alignData.center ? extraSpace / 2 : extraSpace);
+					coord = _curParcel.left + delta;
+					if (line)
+						line.x = coord;
+					textLine.x = coord;
+					
+					adjustedLogicalRight = alignData.lineWidth + coord + Math.max(rightSideGap, 0);
+					_parcelRight = Math.max(adjustedLogicalRight , _parcelRight);
+				}
+			}
+			else
+			{
+				for each (alignData in _alignLines) 
+				{
+					textLine = alignData.textLine;
+					
+					rightSideGap = alignData.rightSidePadding;
+					leftSideGap = alignData.leftSidePadding;
+					leftSideGap += alignData.leftSideIndent;
+					rightSideGap += alignData.rightSideIndent;
+					
+					line = textLine.userData as TextFlowLine;
+					extraSpace = effectiveParcelWidth - leftSideGap - rightSideGap -  textLine.textWidth;
+					delta = leftSideGap + (alignData.center ? extraSpace / 2 : extraSpace);
+					coord = _curParcel.top + delta;
+					if (line)
+						line.y = coord;
+					textLine.y = coord;
+					
+					adjustedLogicalRight = alignData.lineWidth + coord + Math.max(rightSideGap, 0);
+					_parcelBottom = Math.max(adjustedLogicalRight,_parcelBottom);
+				}
+			}
+			_alignLines.length = 0;
+		}
+		
+		protected function commitLastLineState(curLine:TextFlowLine):void
+		{
+			// Remember leading-related state that may be used for laying out the next line
+			_lastLineDescent = curLine.descent;
+			_lastLineLeading = _curLineLeading;
+			_lastLineLeadingModel = _curLineLeadingModel;
+		}
+		
+		protected function doVerticalAlignment(canVerticalAlign:Boolean,nextParcel:Parcel):Boolean
+		{
+			// stub for required override
+			CONFIG::debug { assert(false, "override in derived class"); }
+			return false;
+		}
+		
+		protected function finalParcelAdjustment(controller:ContainerController):void
+		{
+			// stub for required override
+			CONFIG::debug { assert(false, "finalParcelAdjustment missing override in derived class"); }
+		}
+		
+		protected function finishParcel(controller:ContainerController,nextParcel:Parcel):Boolean
+		{
+			if (_curParcelStart == _curElementStart+_curElementOffset)		// empty parcel -- nothing composed into it
+			{
+				CONFIG::debug { assert(_contentLogicalExtent == 0,"bad contentlogicalextent on empty container"); }
+				return false;
+			}
+			
+			// We're only going to align the lines in measurement mode if there's only one parcel
+			var doTextAlign:Boolean = (_alignLines && _alignLines.length > 0); 
+			
+			// Figure out the contents bounds information for the parcel we just finished composing
+			
+			// Content logical height is parcel depth, plus descenders of last line
+			var totalDepth:Number = _parcelList.totalDepth;
+			if (_textFlow.configuration.overflowPolicy == OverflowPolicy.FIT_DESCENDERS && !isNaN(_lastLineDescent))
+				totalDepth += _lastLineDescent;
+			
+			// Initialize the parcel bounds
+			// note we can later optimize away the adjustements
+			if (_blockProgression == BlockProgression.TB)
+			{
+				_parcelLeft = _curParcel.left;
+				_parcelTop = _curParcel.top;
+				_parcelRight = _contentCommittedExtent+_curParcel.left;
+				_parcelBottom = totalDepth+_curParcel.top;
+			}
+			else
+			{
+				// Push the values up to the controller running min/max, if they are bigger
+				_parcelLeft = _curParcel.right-totalDepth;
+				_parcelTop = _curParcel.top;
+				_parcelRight = _curParcel.right;
+				_parcelBottom = _contentCommittedExtent+_curParcel.top;
+			}			
+			if (doTextAlign)
+			{
+				var effectiveParcelWidth:Number;
+				if (_blockProgression == BlockProgression.TB)
+					effectiveParcelWidth = controller.measureWidth ? _contentLogicalExtent : _curParcel.width;
+				else
+					effectiveParcelWidth = controller.measureHeight ? _contentLogicalExtent : _curParcel.height;
+				applyTextAlign(effectiveParcelWidth);
+			}
+			
+			// If we're measuring, then don't do vertical alignment
+			var canVerticalAlign:Boolean = false;
+			if (_blockProgression == BlockProgression.TB)
+			{
+				if (!controller.measureHeight && (!_curParcel.fitAny || _curElementStart + _curElementOffset >= _textFlow.textLength))
+					canVerticalAlign = true;
+			}
+			else
+			{
+				if (!controller.measureWidth && (!_curParcel.fitAny || _curElementStart + _curElementOffset >= _textFlow.textLength))
+					canVerticalAlign = true;
+			}
+			
+			// need to always call this function because internal variables may need resetting
+			if (doVerticalAlignment(canVerticalAlign,nextParcel))
+				doTextAlign = true;
+			// This last adjustment is for two issues
+			// 1) inline graphics that extend above the top (any ILGS I expect)
+			// 2) negative first line indents (stil a worry here?)
+			// If neither of these are present it can be skipped - TODO optimization
+			// trace("BEF finalParcelAdjustment",_parcelLeft,_parcelRight,_parcelTop,_parcelBottom);
+			finalParcelAdjustment(controller);
+			// trace("AFT finalParcelAdjustment",_parcelLeft,_parcelRight,_parcelTop,_parcelBottom);
+			_contentLogicalExtent = 0;
+			_contentCommittedExtent = 0;
+			
+			return true;
+		}
+		
+		/** apply vj and adjust the parcel bounds */
+		protected function applyVerticalAlignmentToColumn(controller:ContainerController,vjType:String,lines:Array,beginIndex:int,numLines:int):void
+		{
+			var firstLine:IVerticalJustificationLine = lines[beginIndex];
+			var lastLine:IVerticalJustificationLine = lines[beginIndex+numLines-1]
+			var firstLineCoord:Number;
+			var lastLineCoord:Number
+			if (_blockProgression == BlockProgression.TB)
+			{
+				firstLineCoord = firstLine.y;
+				lastLineCoord  = lastLine.y;
+			}
+			else
+			{
+				firstLineCoord = firstLine.x;
+				lastLineCoord = lastLine.x;
+			}
+			
+			VerticalJustifier.applyVerticalAlignmentToColumn(controller,vjType,lines,beginIndex,numLines);
+			
+			if (_blockProgression == BlockProgression.TB)
+			{
+				_parcelTop += firstLine.y-firstLineCoord;
+				_parcelBottom += lastLine.y-lastLineCoord;
+			}
+			else
+			{
+				_parcelRight += firstLine.x-firstLineCoord;
+				_parcelLeft += lastLine.x-lastLineCoord;
+			}
+		}
+		
+		private function finishController(controller:ContainerController):void
+		{
+			var controllerTextLength:int = _curElementStart + _curElementOffset - controller.absoluteStart;
+			
+			if (controllerTextLength != 0)
+			{
+				// Leave room for the padding. If the content overlaps the padding, don't count the padding twice.
+				var paddingLeft:Number = controller.effectivePaddingLeft;
+				var paddingTop:Number = controller.effectivePaddingTop;
+				var paddingRight:Number = controller.effectivePaddingRight;
+				var paddingBottom:Number = controller.effectivePaddingBottom;
+				if (_blockProgression == BlockProgression.TB)
+				{
+					if (_controllerLeft > 0)
+					{
+						if (_controllerLeft < paddingLeft)
+							_controllerLeft = 0;
+						else 
+							_controllerLeft -= paddingLeft;
+					}
+					
+					if (_controllerTop > 0)
+					{
+						if (_controllerTop < paddingTop)
+							_controllerTop = 0;
+						else 
+							_controllerTop -= paddingTop;
+					}
+					
+					if (isNaN(controller.compositionWidth))
+						_controllerRight += paddingRight;		 				
+					else if (_controllerRight < controller.compositionWidth)
+					{
+						if (_controllerRight > controller.compositionWidth - paddingRight)
+							_controllerRight = controller.compositionWidth;
+						else 
+							_controllerRight += paddingRight;
+					}
+					_controllerBottom += paddingBottom;	
+				}
+				else
+				{
+					_controllerLeft -= paddingLeft;
+					if (_controllerTop > 0)
+					{
+						if (_controllerTop < paddingTop)
+							_controllerTop = 0;
+						else 
+							_controllerTop -= paddingTop;
+					}
+					if (_controllerRight < 0)
+					{
+						if (_controllerRight > -paddingRight)
+						{
+							_controllerRight = 0;
+						}
+						else
+							_controllerRight += paddingRight;
+					}
+					if (isNaN(controller.compositionHeight))
+						_controllerBottom += paddingBottom;
+					else if (_controllerBottom < controller.compositionHeight)
+					{
+						if (_controllerBottom > controller.compositionHeight - paddingBottom)
+							_controllerBottom = controller.compositionHeight;
+						else 
+							_controllerBottom += paddingBottom;
+					}
+				}
+				controller.setContentBounds(_controllerLeft, _controllerTop, _controllerRight-_controllerLeft, _controllerBottom-_controllerTop);
+			}
+			else
+				controller.setContentBounds(0,0,0,0);
+			
+			controller.setTextLength(controllerTextLength);
+		}
+		
+		private function clearControllers(oldController:ContainerController, newController:ContainerController):void
+		{
+			// any controller between oldController and up to and including newController gets cleared
+			var firstToClear:int = oldController ? _flowComposer.getControllerIndex(oldController)+1 : 0;
+			var lastToClear:int  = newController ? _flowComposer.getControllerIndex(newController) : _flowComposer.numControllers-1;
+			while (firstToClear <= lastToClear)
+			{
+				var controllerToClear:ContainerController = ContainerController(_flowComposer.getControllerAt(firstToClear));
+				controllerToClear.setContentBounds(0, 0, 0, 0);
+				controllerToClear.setTextLength(0);
+				firstToClear++;
+			}
+		}
+		
+		/** This is called when the parcel has changed 
+		 * @param oldParcel - the parcel we had before (you can get the new parcel from the parcel list)
+		 */
+		protected function parcelHasChanged(newParcel:Parcel):void
+		{
+			var oldController:ContainerController = _curParcel ? ContainerController(_curParcel.controller) : null;
+			var newController:ContainerController = newParcel  ? ContainerController(newParcel.controller)  : null;
+			
+			/* if (newParcel)
+			trace("parcelHasChanged newParcel: ",newParcel.clone().toString()); */
+			
+			if (_curParcel != null)
+			{
+				if (finishParcel(oldController,newParcel))
+				{
+					if (_parcelLeft < _controllerLeft)
+						_controllerLeft = _parcelLeft;
+					if (_parcelRight > _controllerRight)
+						_controllerRight = _parcelRight;
+					if (_parcelTop < _controllerTop)
+						_controllerTop = _parcelTop;
+					if (_parcelBottom > _controllerBottom)
+						_controllerBottom = _parcelBottom;
+				}
+			}
+			
+			// update parcel data			
+			if (oldController != newController)		// we're going on to the next controller in the chain
+			{
+				if (oldController)
+					finishController(oldController);
+				
+				resetControllerBounds();
+				
+				if (_flowComposer.numControllers > 1)
+				{
+					if (oldController == null && _startController)
+						clearControllers(_startController, newController);
+					else
+						clearControllers(oldController, newController);
+				}
+				// Parcel list will set totalDepth to newController's paddingTop
+			}
+			_curParcel = newParcel;
+			_curParcelStart = _curElementStart;
+		}
+		/** @private */
+		private function getLineAdjustmentForInline(curLine:TextFlowLine, curLeadingDir:String, isFirstLine:Boolean):LeadingAdjustment
+		{
+			var adjustment:LeadingAdjustment = null;
+			var curTextLine:TextLine = curLine.getTextLine();
+			var para:ParagraphElement = curLine.paragraph;
+			var flowElem:FlowLeafElement = _curElement; //the first element included in this line
+			var curPos:int = flowElem.getAbsoluteStart();
+			var largestPointSize:Number = flowElem.getEffectiveFontSize();
+			var largestImg:Number = 0;
+			
+			//walk
+			while(flowElem && curPos < curLine.absoluteStart + curLine.textLength)
+			{
+				if(curPos >= curLine.absoluteStart || curPos + flowElem.textLength >= curLine.absoluteStart)
+				{	
+					if(flowElem is InlineGraphicElement)
+					{
+						var inlineImg:InlineGraphicElement = flowElem as InlineGraphicElement;
+						//we can ignore TCY for leading adjustments
+						if(!(_blockProgression == BlockProgression.RL && (flowElem.parent is TCYElement)))
+						{
+							//if the largest found img is smaller than the current image, we need new data
+							if(largestImg < inlineImg.getEffectiveFontSize())
+							{
+								largestImg = inlineImg.getEffectiveFontSize();
+								//only get this if the img is as large or larger than the largest found text
+								if(largestImg >= largestPointSize)
+								{
+									largestImg = largestImg;
+									var domBaseline:String = flowElem.computedFormat.dominantBaseline;
+									if(domBaseline == FormatValue.AUTO)
+										domBaseline = LocaleUtil.dominantBaseline(para.computedFormat.locale);
+									
+									//we are only making the adjustment for ideo-center, all others are to be ignored...
+									if(domBaseline == TextBaseline.IDEOGRAPHIC_CENTER)
+									{
+										var elemLeading:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(inlineImg.computedFormat.lineHeight, inlineImg.getEffectiveFontSize());	
+										var curAdjustment:LeadingAdjustment = calculateLinePlacementAdjustment(curTextLine, domBaseline, curLeadingDir, inlineImg, isFirstLine);
+										if(!adjustment || Math.abs(curAdjustment.rise) > Math.abs(adjustment.rise) || Math.abs(curAdjustment.leading) > Math.abs(adjustment.leading))
+										{
+											if(adjustment)
+											{
+												adjustment.rise = curAdjustment.rise;
+												adjustment.leading = curAdjustment.leading;
+											}
+											else
+												adjustment = curAdjustment;
+										}
+									}
+								}
+							}
+						}
+					}
+					else
+					{
+						var tempSize:Number = flowElem.getEffectiveFontSize();
+						if(largestPointSize <= tempSize)
+						{
+							largestPointSize = tempSize;
+						}
+						
+						//if the largest image is smaller than this element, zero out the adjustment
+						if(adjustment && largestImg < largestPointSize)
+						{
+							adjustment.leading = 0;
+							adjustment.rise = 0;
+						}
+					}
+				}
+				
+				//advance the position and get the next element
+				curPos += flowElem.textLength;
+				flowElem = flowElem.getNextLeaf(para);
+			}
+			return adjustment;
+		}
+
+
+		public function get swfContext():ISWFContext
+		{ 
+			var composerContext:ISWFContext = _flowComposer.swfContext;
+			return composerContext ? composerContext : GlobalSWFContext.globalSWFContext; 
+		}
+
+		/** @private */
+		private function calculateLinePlacementAdjustment(curTextLine:TextLine, domBaseline:String, curLeadingDir:String, inlineImg:InlineGraphicElement, isFirstLine:Boolean):LeadingAdjustment
+		{
+			var curAdjustment:LeadingAdjustment = new LeadingAdjustment();
+			//get the leading height for the img
+			var imgHeight:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(inlineImg.computedFormat.lineHeight, inlineImg.getEffectiveFontSize());
+			//get the leading as if the line contains no imgs.  We'll need this to adjust the total adjustments
+			var lineLeading:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(inlineImg.computedFormat.lineHeight, curTextLine.textHeight)
+			
+			//this is a redundant check, but will be needed in the future, so we're leaving it in. - gak 12.16.09
+			if(domBaseline == TextBaseline.IDEOGRAPHIC_CENTER)
+			{
+				if(!isFirstLine)
+				{
+					//for non-first lines, we want to offset the rise of the line
+					curAdjustment.rise += (imgHeight - lineLeading)/2;
+				}
+				else
+				{
+					//for the first line, the offset will be right, but hte leading wrong.
+					curAdjustment.leading -= (imgHeight - lineLeading)/2;
+				}
+			}
+			
+			return curAdjustment;
+		}
+	}
+}
+
+import flash.text.engine.TextLine;
+import flashx.textLayout.compose.ISWFContext;
+import flashx.textLayout.debug.Debugging;
+import flashx.textLayout.tlf_internal;
+
+use namespace tlf_internal;
+
+class AlignData 
+{
+	public var textLine:TextLine;
+	public var lineWidth:Number;
+	public var leftSidePadding:Number;
+	public var rightSidePadding:Number;
+	public var center:Boolean;
+	public var leftSideIndent:Number;
+	public var rightSideIndent:Number;
+}
+
+
+class GlobalSWFContext implements ISWFContext
+{
+	static public const globalSWFContext:GlobalSWFContext = new GlobalSWFContext();
+
+	public function GlobalSWFContext()
+	{ }
+	
+	public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
+	{
+		CONFIG::debug
+		{
+			var rslt:*
+			try
+			{
+				if (returns)
+					rslt = fn.apply(thisArg, argsArray);
+
+				else
+					fn.apply(thisArg, argsArray);
+					
+				if (thisArg)
+				{
+					var traceArgs:Array;
+					// later make this table driven
+					if (thisArg.hasOwnProperty("createTextLine") && fn == thisArg["createTextLine"])
+					{
+						traceArgs = [rslt,thisArg,"createTextLine"]
+						traceArgs.push.apply(traceArgs, argsArray);
+						Debugging.traceFTECall.apply(null,traceArgs);
+					}
+					else if (thisArg.hasOwnProperty("recreateTextLine") && fn == thisArg["recreateTextLine"])
+					{
+						traceArgs = [rslt,thisArg,"recreateTextLine"]
+						traceArgs.push.apply(traceArgs, argsArray);
+						Debugging.traceFTECall.apply(null,traceArgs);
+					}
+				}
+			}
+			catch(e:Error)
+			{
+				// trace(e);
+				throw(e);
+			}
+			return rslt;
+		}
+		CONFIG::release
+		{
+			if (returns)
+				return fn.apply(thisArg, argsArray);
+			fn.apply(thisArg, argsArray);
+		}
+	}
+}
+
+class LeadingAdjustment
+{
+	public var rise:Number = 0;
+	public var leading:Number = 0;
+	public var lineHeight:Number = 0;
+}
+
+
diff --git a/textLayout_core/src/flashx/textLayout/compose/ComposeState.as b/textLayout_core/src/flashx/textLayout/compose/ComposeState.as
new file mode 100755
index 0000000..3cf15fb
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/ComposeState.as
@@ -0,0 +1,406 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.events.Event;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.OverflowPolicy;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.BaselineOffset;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextAlign;
+	import flashx.textLayout.formats.VerticalAlign;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** Keeps track of internal state during composition. 
+	 * 
+	 * This is the simpler version, used when there are no floats, no wraps, no columns.
+	 * @private
+	 */
+	public class ComposeState extends BaseCompose 
+	{
+		/** Index of current line */
+		protected var _curLineIndex:int;	
+		
+		// for figuring out when to do VJ
+		protected var vjBeginLineIndex:int;
+		protected var vjDisableThisParcel:Boolean;
+		
+		// a single ComposeState that is checked out and checked in
+		static private var _sharedComposeState:ComposeState;
+
+		/** @private */
+		static tlf_internal function getComposeState():ComposeState
+		{
+			var rslt:ComposeState = _sharedComposeState ? _sharedComposeState : new ComposeState();
+			_sharedComposeState = null;
+			return rslt;
+		}
+		
+		/** @private */
+		static tlf_internal function releaseComposeState(state:ComposeState):void
+		{
+			if (_sharedComposeState == null)
+			{
+				_sharedComposeState = state;
+				if (_sharedComposeState)
+					_sharedComposeState.releaseAnyReferences();
+			}
+		}
+
+		/** Constructor. */
+		public function  ComposeState()
+		{	
+			super();	
+		}				
+
+		/** @private */
+		protected override function createParcelList():IParcelList
+		{
+			return ParcelList.getParcelList();
+		}
+		/** @private */
+		protected override function releaseParcelList(list:IParcelList):void
+		{
+			ParcelList.releaseParcelList(list);
+		}
+		
+		/** @private */
+		public override function composeTextFlow(textFlow:TextFlow, composeToPosition:int, controllerEndIndex:int):int
+		{
+			_curLineIndex    = 0;
+					
+			vjBeginLineIndex = 0;
+			vjDisableThisParcel = false;
+			
+			return super.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+		}
+		
+		protected override function initializeForComposer(composer:IFlowComposer,composeToPosition:int,controllerEndIndex:int):void
+		{
+			super.initializeForComposer(composer,composeToPosition,controllerEndIndex);
+			           
+			var controllerIndex:int = composer.findControllerIndexAtPosition(composer.damageAbsoluteStart);
+			if (controllerIndex == -1)
+			{
+				controllerIndex = composer.numControllers-1;
+				// if off the end in the overflow - find the last non-zero controller
+				while (controllerIndex != 0 && composer.getControllerAt(controllerIndex).textLength == 0)
+					controllerIndex--;
+			}
+			// if damage is in overflow after last controller we could get smart about that
+			_startController = composer.getControllerAt(controllerIndex);
+			CONFIG::debug { assert(_startController != null,"Bad start start controller"); }
+			_startComposePosition = _startController.absoluteStart;
+		}
+		
+		/** @private */
+		protected override function composeInternal(composeRoot:FlowGroupElement,absStart:int):void
+		{
+			super.composeInternal(composeRoot,absStart);
+			
+			// mark all overflow lines as not being in any container or column
+			if (_curElement)
+			{
+				CONFIG::debug { assert(_curLineIndex == _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset),"bad _curLineIndex"); }
+				while (_curLineIndex < _flowComposer.numLines)
+					_flowComposer.getLineAt(_curLineIndex++).setController(null,-1);
+			}
+		}
+
+ 		override protected function doVerticalAlignment(canVerticalAlign:Boolean,nextParcel:Parcel):Boolean
+		{
+			var result:Boolean = false;
+			if (canVerticalAlign && _curParcel && vjBeginLineIndex != _curLineIndex &&  !vjDisableThisParcel && _curParcel.columnCoverage == Parcel.FULL_COLUMN)
+			{
+				var controller:ContainerController = _curParcel.controller;
+				var vjtype:String = controller.computedFormat.verticalAlign;
+				if (vjtype != VerticalAlign.TOP)
+				{	
+					// Exclude overset lines
+					var end:int = _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset)
+
+					if (vjBeginLineIndex < end)
+					{
+						applyVerticalAlignmentToColumn(controller,vjtype,_flowComposer.lines,vjBeginLineIndex,end-vjBeginLineIndex);
+						result = true;	// lines were moved
+					}
+				}
+			}
+			
+			// always reset these variables
+			vjDisableThisParcel = false;
+			vjBeginLineIndex = _curLineIndex;	
+			
+			return result;
+		}
+		
+		/** Final adjustment on the content bounds. */
+ 		override protected function finalParcelAdjustment(controller:ContainerController):void
+ 		{
+ 			var minX:Number = TextLine.MAX_LINE_WIDTH;
+ 			var minY:Number = TextLine.MAX_LINE_WIDTH;
+ 			var maxX:Number = -TextLine.MAX_LINE_WIDTH;
+ 			var maxY:Number = -TextLine.MAX_LINE_WIDTH;
+ 			
+ 			var verticalText:Boolean = _blockProgression == BlockProgression.RL;
+
+            var lineIndex:int = _flowComposer.findLineIndexAtPosition(controller.absoluteStart); 
+            while (lineIndex < _curLineIndex)
+            {
+            	var line:TextFlowLine = _flowComposer.getLineAt(lineIndex);
+
+            	// Check the logical vertical dimension first
+            	// If the lines have children, they may be inlines. The origin of the TextFlowLine is the baseline - ascent, 
+            	// which does not include the ascent of the inlines. So we have to factor that in.
+				if (verticalText)
+				{
+	      	 		maxX = Math.max(line.x + line.ascent, maxX);
+	      	 		minX = Math.min(line.x, minX);
+	   			}	
+	      	 	else
+	      	 		minY = Math.min(line.y, minY);
+	       		var textLine:TextLine = line.getTextLine();
+	       		
+	       		// this is a test for an inline graphic
+	       		if (textLine.hasGraphicElement)
+	       		{
+	       			var leafElement:FlowLeafElement = _textFlow.findLeaf(line.absoluteStart);
+	       			var adjustedAscent:Number = line.getLineTypographicAscent(leafElement, leafElement.getAbsoluteStart());
+					if (!verticalText)
+	       				minY = Math.min(line.y + line.ascent - adjustedAscent, minY);
+	       			else
+	       				maxX = Math.max(line.x + adjustedAscent, maxX);
+	       		}
+
+
+				// Now check the logical horizontal dimension
+				var edgeAdjust:Number;
+				var curParaFormat:ITextLayoutFormat = line.paragraph.computedFormat;
+				if (curParaFormat.direction == Direction.LTR)
+					edgeAdjust = Math.max(line.lineOffset, 0);
+				else
+					edgeAdjust = curParaFormat.paragraphEndIndent;
+             	if (verticalText)
+           			minY = Math.min(line.y - edgeAdjust, minY);
+             	else 
+           			minX = Math.min(line.x - edgeAdjust, minX);
+            	++lineIndex;
+            }
+            
+            if (_blockProgression == BlockProgression.RL)
+            	minX -= _lastLineDescent;
+            
+            // Don't make adjustments for tiny fractional values.
+            if (minX != TextLine.MAX_LINE_WIDTH && Math.abs(minX-_parcelLeft) >= 1)
+         		_parcelLeft = minX;
+            if (maxX != -TextLine.MAX_LINE_WIDTH && Math.abs(maxX-_parcelRight) >= 1)
+         		_parcelRight = maxX;
+         	if (minY != TextLine.MAX_LINE_WIDTH && Math.abs(minY-_parcelTop) >= 1)
+           		_parcelTop = minY;
+         	if (maxY != -TextLine.MAX_LINE_WIDTH && Math.abs(maxY-_parcelBottom) >= 1)
+           		_parcelBottom = maxY;
+ 		}
+ 				
+		private function finalizeLine(useExistingLine:Boolean,curLine:TextFlowLine):void
+		{
+			if ( !useExistingLine ) 		
+			{	
+				_flowComposer.addLine(curLine,_curLineIndex);
+			}
+			_curLineIndex++;
+			
+			commitLastLineState (curLine);
+		}
+		
+		protected override function composeParagraphElement(elem:ParagraphElement, absStart:int):Boolean
+		{
+			_curParaElement  = elem;
+			_curParaStart    = absStart;
+			_curParaFormat = elem.computedFormat;
+			CONFIG::debug { assert(_curParaStart == elem.getAbsoluteStart(),"composeParagraphElement: bad start"); }
+			if (_startComposePosition == 0)
+			{
+				_curElement 	 = elem.getFirstLeaf();
+				_curElementStart = _curParaStart;
+			}
+			else 
+			{
+				CONFIG::debug { assert(absStart <= _startComposePosition && absStart+elem.textLength > _startComposePosition,"bad call to composeParagraphElement"); }
+				_curElement = elem.findLeaf(_startComposePosition-absStart);
+				_curElementStart = _curElement.getAbsoluteStart();
+				_curElementOffset = _startComposePosition-_curElementStart;
+				_curLineIndex = _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset);
+				// next time we are all postioned
+				_startComposePosition = 0;
+			}
+
+			return composeParagraphElementIntoLines();
+		}
+		
+		/** @private */
+		protected override function composeNextLine():TextFlowLine
+		{
+			CONFIG::debug { assert(_curLineIndex == _flowComposer.findLineIndexAtPosition(_curElementStart + _curElementOffset),"bad _curLineIndex"); }
+
+			// Check to see if there's an existing line that is composed up-to-date
+			var line:TextFlowLine = _curLineIndex < _flowComposer.numLines ? _flowComposer.lines[_curLineIndex] : null;
+			var useExistingLine:Boolean = line && (!line.isDamaged() || line.validity == FlowDamageType.GEOMETRY);
+			var curLine:TextFlowLine = useExistingLine ? line : null;
+			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
+			var prevLine:TextFlowLine;
+			if (startCompose != 0)
+			{
+				prevLine = _flowComposer.lines[_curLineIndex - 1];
+				if (prevLine.absoluteStart < _curParaStart)		// is the previous line in the previous paragraph?
+					prevLine = null;
+			}
+			var finishLineSlug:Rectangle = _parcelList.currentParcel;
+			
+			for (;;) 
+			{
+				while (!curLine)
+				{	
+					useExistingLine = false;
+					// generate new line
+					CONFIG::debug { assert(!_parcelList.atEnd(), "failing to stop"); }
+					CONFIG::debug { assert(_curElement is FlowLeafElement, "element must be leaf before calling composeLine"); }
+					
+					curLine = createTextLine(prevLine,	startCompose, _parcelList.getComposeXCoord(finishLineSlug), _parcelList.getComposeYCoord(finishLineSlug),	_parcelList.getComposeWidth(finishLineSlug));
+					if (curLine != null)
+						break;
+					// force advance to the next parcel
+					if (!_parcelList.next())
+						return null;
+				}
+				
+				// updates _lineSlug
+				curLine = fitLineToParcel(curLine, !useExistingLine);
+				if (curLine)
+					break;
+				if (_parcelList.atEnd())
+					return null;
+				finishLineSlug = _lineSlug;
+			}
+			
+			// Clear up user_invalid
+			if (curLine.validity == FlowDamageType.GEOMETRY)
+				curLine.clearDamage(); 
+								
+			finalizeLine(useExistingLine,curLine);
+
+			CONFIG::debug { assert(curLine != null, "curLine != null"); }			
+			return curLine;
+		}
+		
+		/** @private */
+		protected function createTextLine(prevLine:TextFlowLine,	// previous line
+			lineStart:int, 		// text index of position to start from, relative to start of paragraph
+			x:Number,			// left edge of the line
+			y:Number, 			// top of the line
+			targetWidth:Number	// target width we're composing into
+			):TextFlowLine
+        {
+        //	trace("lineBreak: start", prevLine ? (prevLine.start+prevLine.textLength) : 0, "paraEnd", paraEnd, "(", x, y, ")", "targetWidth", targetWidth);
+         	
+        	CONFIG::debug { validateLineStart(prevLine, lineStart, _curParaElement); }
+        	
+ 			var lineOffset:Number = Number(_curParaFormat.paragraphStartIndent);  	// indent to "beginning" of the line.  Direction dependent (as is paragraphStartIndent)    		
+     		if (prevLine == null) 	// first line indent
+     			lineOffset += Number(_curParaFormat.textIndent);
+     		
+     		var outerTargetWidth:Number = targetWidth;
+     		targetWidth -= (Number(_curParaFormat.paragraphEndIndent) + lineOffset);		// make room for offset and end indent
+     		
+     		// TargetWidth must be between 0 and TextLine.MAX_LINE_WIDTH
+     		if (targetWidth < 0)
+     			targetWidth = 0;
+     		else if (targetWidth > TextLine.MAX_LINE_WIDTH)
+     			targetWidth = TextLine.MAX_LINE_WIDTH;
+	   		
+	   		var textLine:TextLine = TextLineRecycler.getLineForReuse();
+	   		var textBlock:TextBlock = _curParaElement.getTextBlock();
+	   		if (textLine)
+	   		{
+				CONFIG::debug { assert(_textFlow.backgroundManager == null || _textFlow.backgroundManager.lineDict[textLine] === undefined,"Bad TextLine in recycler cache"); }
+	        	textLine = swfContext.callInContext(textBlock["recreateTextLine"],textBlock,[textLine, prevLine?prevLine.getTextLine(true):null, targetWidth, lineOffset, true]);
+      		}
+	   		else
+	   		{
+	        	textLine = swfContext.callInContext(textBlock.createTextLine,textBlock,[prevLine?prevLine.getTextLine(true):null, targetWidth, lineOffset, true]);
+      		}
+        	// Unable to fit a new line
+        	if (textLine == null)
+        		return null;
+        	//trace("LineBreak prevLineLength:",prevLine?prevLine.textLine.rawTextLength:0,"nextLineLength:",line?line.textLine.rawTextLength:0);
+ 			// outerTargetWidth, targetWidth, textIndent, start, textLength, textLine
+ 			CONFIG::debug { assert(_curParaStart == _curParaElement.getAbsoluteStart(),"bad _curParaStart"); }
+ 			var line:TextFlowLine = new TextFlowLine(textLine, _curParaElement, outerTargetWidth, lineOffset, lineStart + _curParaStart, textLine.rawTextLength);
+ 			CONFIG::debug { assert(line.targetWidth == targetWidth,"Bad targetWidth"); }
+ 			textLine.doubleClickEnabled = true;		// allow line to be the target oif a double click event
+ 			
+			// update spaceBefore & spaceAfter		
+			var linePos:uint = line.location;
+			if (linePos & TextFlowLineLocation.FIRST)
+				line.setSpaceBefore(Number(_curParaFormat.paragraphSpaceBefore));
+			if (linePos & TextFlowLineLocation.LAST)
+	     		line.setSpaceAfter(Number(_curParaFormat.paragraphSpaceAfter)); 			
+ 			
+ 			return line;
+        }
+        
+        /** @private */
+		CONFIG::debug private static function validateLineStart(prevLine:TextFlowLine, lineStart:int, paraNode:ParagraphElement):void
+		{
+			// If the lines have been released, don't validate
+			if (lineStart != 0 && paraNode.getTextBlock().firstLine == null)
+				return;
+				
+	       	var testStart:int = 0;
+	    	var testLine:TextLine = prevLine ? prevLine.getTextLine(true) : null;
+	    	while (testLine)
+	    	{
+	    		testStart += testLine.rawTextLength;
+	    		testLine = testLine.previousLine;
+	    	}
+	    	assert(testStart == lineStart, "Bad lines");
+			
+      		assert(paraNode is ParagraphElement,"composeLine: paraNode must be a para"); 
+      		assert(!prevLine || !(prevLine.location & TextFlowLineLocation.LAST),"prevLine may not be from a different para"); 
+		} 
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/FlowComposerBase.as b/textLayout_core/src/flashx/textLayout/compose/FlowComposerBase.as
new file mode 100755
index 0000000..0ab0cf4
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/FlowComposerBase.as
@@ -0,0 +1,637 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{	
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.BackgroundManager;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	[Exclude(name="initializeLines",kind="method")]
+	[Exclude(name="addLine",kind="method")]
+	[Exclude(name="lines",kind="property")]
+	[Exclude(name="debugCheckTextFlowLines",kind="method")]
+	[Exclude(name="checkFirstDamage",kind="method")]
+	
+	/** 
+	 * The FlowComposerBase class is the base class for Text Layout Framework flow composer classes, which control the 
+	 * composition of text lines in ContainerController objects.
+	 *
+	 * <p>FlowComposerBase is a utility class that implements methods and properties that are common
+	 * to several types of flow composer. Application code would not typically instantiate or use this class
+	 * (unless extending it to create a custom flow composer).</p>
+	 * 
+	 * @see flashx.textLayout.elements.TextFlow#flowComposer
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	public class FlowComposerBase
+	{
+				// Composition data
+		[ ArrayElementType("text.elements.TextFlowLine") ]
+		private var _lines:Array;	
+		
+		/** @private */
+		protected var _textFlow:TextFlow;
+		
+		/** Absolute start of the damage area -- first character in the flow that is dirty and needs to be recomposed. @private */
+		protected var _damageAbsoluteStart:int;
+		
+		/** @private */
+		protected var _swfContext:ISWFContext;
+		
+		/** Constructor. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function FlowComposerBase():void
+		{
+			_lines = new Array();
+			_swfContext = null;
+		}
+		
+		/** Returns the array of lines. @private */
+		public function get lines():Array
+		{ return _lines; }
+		
+		/** 
+		 * @copy IFlowComposer#getLineAt()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function getLineAt(index:int):TextFlowLine
+		{ return _lines[index]; }
+		
+		/** @copy IFlowComposer#numLines 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get numLines():int
+		{ return _lines.length; }
+		
+		/** 
+		* The TextFlow object to which this flow composer is attached. 
+		*
+		* @see flashx.textLayout.elements.TextFlow
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function get textFlow():TextFlow
+		{ return _textFlow; }
+		
+		/**
+		 * The absolute position immediately preceding the first element in the text
+		 * flow that requires composition and updating.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function get damageAbsoluteStart():int
+		{
+			return _damageAbsoluteStart;
+		}
+		
+		/**
+		 * Initialize the lines for the TextFlow.  Creates a single TextFlowLine with no content. @private
+		 */ 
+		protected function initializeLines():void
+		{
+			var backgroundManager:BackgroundManager = _textFlow ? _textFlow.backgroundManager : null;
+			// remove all the lines we have now - cache for reuse
+			if (TextLineRecycler.textLineRecyclerEnabled)
+			{
+				for each (var line:TextFlowLine in _lines)
+				{
+					var textLine:TextLine = line.peekTextLine();
+					if (textLine && !textLine.parent)
+					{
+						// releasing all textLines so release each still connected textBlock
+						if (textLine.validity != TextLineValidity.INVALID)
+						{
+							var textBlock:TextBlock = textLine.textBlock;
+							CONFIG::debug { Debugging.traceFTECall(null,textBlock,"releaseLines",textBlock.firstLine,textBlock.lastLine); }
+							textBlock.releaseLines(textBlock.firstLine,textBlock.lastLine);
+						}
+						textLine.userData = null;
+						TextLineRecycler.addLineForReuse(textLine);
+						if (backgroundManager)
+							backgroundManager.removeLineFromCache(textLine);
+					}
+				}
+			}
+			_lines.splice(0);
+			_damageAbsoluteStart = 0;
+			
+			CONFIG::debug { checkFirstDamaged(); }
+		}
+		
+		/** Make sure that there is a TextFlowLine for all the content - even if compose has stopped early. @private */
+		protected function finalizeLinesAfterCompose():void
+		{
+			var line:TextFlowLine;
+			if (_lines.length == 0)
+			{
+				// create a new line, with damage, that covers the entire area
+				line = new TextFlowLine(null,null);
+				line.setTextLength(textFlow.textLength);
+				_lines.push(line);
+			}
+			else
+			{
+				line = _lines[_lines.length-1];
+				var lineEnd:int = line.absoluteStart + line.textLength;
+				if (lineEnd < textFlow.textLength)
+				{
+					line = new TextFlowLine(null,null);
+					line.setAbsoluteStart(lineEnd);
+					line.setTextLength(textFlow.textLength-lineEnd);
+					_lines.push(line);
+				}
+			}			
+		}
+		
+		/** 
+		 * @copy IFlowComposer#updateLengths()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function updateLengths(startPosition:int,deltaLength:int):void
+		{
+			// no lines yet - skip it
+			if (numLines == 0)
+				return;
+				
+			var line:TextFlowLine;	// sratch line variable
+			var lineIdx:int = findLineIndexAtPosition(startPosition);
+				
+			var damageStart:int = int.MAX_VALUE;			
+			if (deltaLength > 0)
+			{
+				if (lineIdx == _lines.length)
+				{
+					line = _lines[_lines.length-1];
+					CONFIG::debug { assert(line.absoluteStart+line.textLength == startPosition,"updateLengths bad startIdx"); }
+					line.setTextLength(line.textLength + deltaLength);
+				}
+				else
+				{
+					line = _lines[lineIdx++];
+					line.setTextLength(line.textLength + deltaLength);
+				}
+				damageStart = line.absoluteStart;
+			}
+			else
+			{
+				var lenToDel:int = -deltaLength;
+				var curPos:int = 0;
+				
+				while (true)
+				{
+					line = _lines[lineIdx];
+					line.setAbsoluteStart(line.absoluteStart + lenToDel + deltaLength);
+					curPos = (startPosition > line.absoluteStart ? startPosition : line.absoluteStart);
+					
+					var lineEndIdx:int = line.absoluteStart + line.textLength;
+					var deleteChars:int = 0;
+					
+					if (curPos + lenToDel <= lineEndIdx)		
+					{
+						if (curPos == line.absoluteStart)
+							deleteChars = lenToDel;				//delete from begin of line to end of selection
+						else if (curPos == startPosition)
+							deleteChars = lenToDel;				//delete is all included in one line
+						else
+						{
+							CONFIG::debug { assert(false, "insertText: should never happen");  }
+						}								
+					}
+					else //(curPos + lenToDel > lineEndIdx)		//multiline delete
+					{
+						if (curPos == line.absoluteStart)
+							deleteChars = line.textLength; 		//delete the whole line
+						else
+							deleteChars = lineEndIdx-curPos;	//delete from middle of line to end of line
+					}		
+						
+					if (curPos == line.absoluteStart && curPos + deleteChars == lineEndIdx)		//the whole line is selected
+					{
+						lenToDel -= deleteChars;
+						_lines.splice(lineIdx,1);			//lineIdx now points to the next line
+					}
+					else 									//partial line
+					{
+						if (damageStart > line.absoluteStart)
+							damageStart = line.absoluteStart;
+						line.setTextLength(line.textLength - deleteChars);
+						lenToDel -= deleteChars;
+						lineIdx++;
+					}
+					CONFIG::debug { assert(lenToDel >= 0,"updateLengths deleted too much"); }
+					if (lenToDel <= 0)
+							break;						
+				}
+			}
+			
+			for ( ; lineIdx < _lines.length; lineIdx++)
+			{
+				line = _lines[lineIdx];
+				if (deltaLength >= 0)
+					line.setAbsoluteStart(line.absoluteStart  + deltaLength);
+				else
+					line.setAbsoluteStart(line.absoluteStart > -deltaLength ? line.absoluteStart+deltaLength : 0);
+			}
+			
+			if (_damageAbsoluteStart > damageStart)
+				_damageAbsoluteStart = damageStart;
+		}
+		
+		/** 
+		 * @copy IFlowComposer#damage()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function damage(startPosition:int, damageLength:int, damageType:String):void
+		{
+			// find the line at damageStart
+			if (_lines.length == 0 || textFlow.textLength == 0)
+				return;
+				
+			// This case the damageStart is at the end of the text.  This can happen if the last paragraph is deleted
+			if (startPosition == textFlow.textLength)
+				return;
+				
+			CONFIG::debug { assert(startPosition + damageLength <= textFlow.textLength, "Damaging past end of flow!"); }
+			
+			// Start damaging one line before the startPosition location in case some of the first "damaged" line will fit on the previous line.
+			// We do this only if we're not on the first line of the paragraph -- figuring this out is expensive but otherwise we could damage
+			// back while we're composing because we damaged in the process of constructing a textBlock.
+			var lineIndex:int = findLineIndexAtPosition(startPosition);
+			var leaf:FlowLeafElement = textFlow.findLeaf(startPosition);
+			if (leaf && lineIndex > 0 && leaf.getParagraph().getAbsoluteStart() != startPosition)
+				lineIndex--;
+
+			if (lines[lineIndex].absoluteStart < _damageAbsoluteStart)
+				_damageAbsoluteStart = _lines[lineIndex].absoluteStart;
+				
+			CONFIG::debug { assert(lineIndex < _lines.length && _lines[lineIndex].absoluteStart <= startPosition + damageLength, "Missing line"); }
+			
+			while (lineIndex < _lines.length)
+			{
+				var line:TextFlowLine = _lines[lineIndex];
+				
+				// Changed to >= from >, as > seemed to damage too
+				// many lines when editing tables. 
+				// Should verify the correctness of this.
+				if (line.absoluteStart >= startPosition+damageLength)
+					break;
+				
+				line.damage(damageType);
+				lineIndex++;
+			}
+		}
+		
+		/**
+		 * @copy IFlowComposer#isDamaged()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function isDamaged(absolutePosition:int):Boolean
+		{
+			// Returns true if any text from _damageAbsoluteStart through absolutePosition needs to be recomposed
+			
+			// no lines - damaged
+			if (_lines.length == 0)
+				return true;
+				
+			CONFIG::debug { checkFirstDamaged(); }
+
+			return _damageAbsoluteStart <= absolutePosition && _damageAbsoluteStart != textFlow.textLength;
+		}
+
+		/** @private */
+		CONFIG::debug public function checkFirstDamaged():void
+		{
+			// find the line at start
+			if (_lines.length == 0)
+				return;
+				
+			var lineIndex:int = findLineIndexAtPosition(0);
+			while (lineIndex < _lines.length)
+			{
+				if (_lines[lineIndex].isDamaged())
+				{
+				//	trace("is damaged");
+					CONFIG::debug { assert(_lines[lineIndex].absoluteStart >= _damageAbsoluteStart, "_damageAbsoluteStart doesn't match actual line value"); } 
+					return;
+				}
+				++lineIndex;				
+			}
+		//	trace("not damaged");
+			return;
+		}
+		/** 
+		 * @copy IFlowComposer#findLineIndexAtPosition()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function findLineIndexAtPosition(absolutePosition:int,preferPrevious:Boolean = false):int
+		{	
+			var lo:int = 0;
+			var hi:int = _lines.length-1;
+			while (lo <= hi)
+			{
+				var mid:int = (lo+hi)/2;
+				var line:TextFlowLine = _lines[mid];
+				if (line.absoluteStart <= absolutePosition)
+				{
+					if (preferPrevious)
+					{
+						if (line.absoluteStart + line.textLength >= absolutePosition)
+							return mid;
+					}
+					else
+					{
+						if (line.absoluteStart + line.textLength > absolutePosition)
+							return mid;
+					}
+					lo = mid+1;
+				}
+				else
+					hi = mid-1;
+			}
+			return _lines.length;
+		}
+		
+		/**
+		 * @copy IFlowComposer#findLineAtPosition()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function findLineAtPosition(absolutePosition:int,preferPrevious:Boolean = false):TextFlowLine
+		{
+			return _lines[findLineIndexAtPosition(absolutePosition,preferPrevious)];
+		}
+		
+		/**
+		 * add a new line 
+		 * Add a new line to the list of composed lines for the frame. Lines are sorted
+		 * by the start location, and each line has a span. The start of the next line
+		 * has to match the start of the previous line + the span of the previous line.
+		 * The last line needs to end at the end of the text. Therefore, when we add a
+		 * new line, we may need to adjust the span and/or start locations of other lines 
+		 * in the text.
+		 * @private
+		 */
+		public function addLine(newLine:TextFlowLine,workIndex:int):void
+		{
+			CONFIG::debug { assert(workIndex == findLineIndexAtPosition(newLine.absoluteStart),"bad workIndex to TextFlow.addLine"); };
+			CONFIG::debug { assert (!newLine.isDamaged(), "adding damaged line"); }
+			var workLine:TextFlowLine = _lines[workIndex];
+			var afterLine:TextFlowLine;
+			var damageStart:int = int.MAX_VALUE;
+			if (_damageAbsoluteStart == newLine.absoluteStart)
+				_damageAbsoluteStart = newLine.absoluteStart + newLine.textLength;
+				
+			if (workLine == null)
+				lines.push(newLine);				
+			else if (workLine.absoluteStart != newLine.absoluteStart)
+			{
+				if (workLine.absoluteStart + workLine.textLength > newLine.absoluteStart + newLine.textLength)
+				{
+					// Making a new line in the middle of an old one. Need to split the old one.
+					afterLine = new TextFlowLine(null,newLine.paragraph);
+					afterLine.setAbsoluteStart(newLine.absoluteStart + newLine.textLength);
+					var oldCharCount:int = workLine.textLength;
+					workLine.setTextLength(newLine.absoluteStart - workLine.absoluteStart);
+					CONFIG::debug { assert(workLine.textLength != 0, "0 width line"); }
+					afterLine.setTextLength((oldCharCount - newLine.textLength) - workLine.textLength);
+					CONFIG::debug { assert(afterLine.textLength != 0, "0 width line"); }
+					_lines.splice(workIndex + 1, 0, newLine, afterLine);
+				}
+				else
+				{
+					// We're composing ahead, so we need to split the line where we're at
+					// This can happen if a table is getting composed, some cells can be composed before 
+					// others that go before. 
+					CONFIG::debug { assert(workLine.isDamaged(), "Uneven line boundary, but lines marked up to date"); }
+					workLine.setTextLength(newLine.absoluteStart - workLine.absoluteStart);
+					CONFIG::debug { assert(workLine.textLength != 0, "0 width line"); }
+					afterLine = _lines[workIndex+1];
+					afterLine.setTextLength((newLine.absoluteStart + newLine.textLength) - afterLine.absoluteStart);
+					CONFIG::debug { assert(_lines[workIndex + 1].textLength != 0, "0 width line"); }
+					afterLine.setAbsoluteStart(newLine.absoluteStart + newLine.textLength);
+					_lines.splice(workIndex + 1, 0, newLine);
+				}
+				damageStart = workLine.absoluteStart;
+			}
+			else if (workLine.textLength > newLine.textLength)
+			{
+				// New line partially overlaps old line.
+				// Keep the old line, but resize it so it comes after the new line.
+				// Insert the new line at the old line's position
+				workLine.setTextLength(workLine.textLength - newLine.textLength);
+				CONFIG::debug { assert(workLine.textLength != 0, "0 width line"); }
+				workLine.setAbsoluteStart(newLine.absoluteStart + newLine.textLength);
+				workLine.damage(TextLineValidity.INVALID);
+				_lines.splice(workIndex, 0, newLine);
+				damageStart = workLine.absoluteStart;
+			}
+			else 
+			{
+				var deleteCount:int = 1;
+				// The new line completely overlaps the old line.
+				// Insert the new line over the old line. If the line extents don't match,
+				// fix-up the starting position & extent of the following line.
+				if (workLine.textLength != newLine.textLength)
+				{
+					var amtRemaining:int = (newLine.textLength - workLine.textLength);
+					var nextLine:int = workIndex + 1;
+					while (amtRemaining > 0)
+					{
+						afterLine = _lines[nextLine];
+						if (amtRemaining < afterLine.textLength)
+						{
+							afterLine.setTextLength(afterLine.textLength - amtRemaining);
+							afterLine.damage(TextLineValidity.INVALID);
+							break;
+						}
+						else
+						{
+							deleteCount++;
+							amtRemaining -= afterLine.textLength;
+							nextLine++;
+							afterLine = nextLine < _lines.length ? _lines[nextLine] : null
+						}
+					}
+					if (afterLine && afterLine.absoluteStart != newLine.absoluteStart + newLine.textLength)
+					{
+						afterLine.setAbsoluteStart(newLine.absoluteStart + newLine.textLength);
+						afterLine.damage(TextLineValidity.INVALID);
+						CONFIG::debug { assert(afterLine.textLength != 0, "0 width line"); }
+					}
+					damageStart = newLine.absoluteStart + newLine.textLength;
+				}
+				// remove userData on the deleted lines so they can be recycled
+				if (TextLineRecycler.textLineRecyclerEnabled)
+				{
+					var backgroundManager:BackgroundManager = textFlow.backgroundManager;
+					for (var recycleIdx:int = workIndex; recycleIdx < workIndex+deleteCount; recycleIdx++)
+					{
+						var textLine:TextLine = TextFlowLine(_lines[recycleIdx]).peekTextLine();
+						if (textLine && !textLine.parent)
+						{
+							// lines shouldn't be valid here but lets check anyhow
+							CONFIG::debug { assert(textLine.validity != TextLineValidity.VALID,"caught a bug here"); }
+							if (textLine.validity != TextLineValidity.VALID)	// recycle immediately if not parented
+							{
+								textLine.userData = null;
+								TextLineRecycler.addLineForReuse(textLine);
+								if (backgroundManager)
+									backgroundManager.removeLineFromCache(textLine);
+							}
+						}
+					}
+				}
+				_lines.splice(workIndex, deleteCount, newLine);
+			}
+	
+			if (_damageAbsoluteStart > damageStart)
+				_damageAbsoluteStart = damageStart;
+			// CONFIG::debug { debugCheckTextFlowLines(false); }
+	//		CONFIG::debug { checkFirstDamaged(); }	 enabling this will cause false positives due to _damageAbsoluteStart during composition not updated	when GEOMETRY_DAMAGE lines are cleared
+		}
+		
+		/** @private - helper function for finding a base swf context from a swf context */
+		tlf_internal static function computeBaseSWFContext(context:ISWFContext):ISWFContext
+		{
+			return context && Object(context).hasOwnProperty("getBaseSWFContext") ? context["getBaseSWFContext"]() : context;
+		}
+		/** 
+		* The ISWFContext instance used to make FTE calls as needed. 
+		*
+		* <p>By default, the ISWFContext implementation is this FlowComposerBase object.
+		* Applications can provide a custom implementation to use fonts
+		* embedded in a different SWF file or to cache and reuse text lines.</p>
+		* 
+		* @see flashx.textLayout.compose.ISWFContext
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+ 	
+		public function get swfContext():ISWFContext
+		{
+			return _swfContext;
+		}
+		public function set swfContext(context:ISWFContext):void
+		{
+			if (context != _swfContext)
+			{
+				// swf contexts can be wrappers for other swf contexts - we're going to let the swfcontext give us a hint here
+				if (textFlow)
+				{
+					var newBaseContext:ISWFContext =  computeBaseSWFContext(context);
+					var oldBaseContext:ISWFContext =  computeBaseSWFContext(_swfContext);
+	
+					_swfContext = context;
+
+					if (newBaseContext != oldBaseContext)
+					{
+						damage(0,textFlow.textLength,FlowDamageType.INVALID);
+						textFlow.invalidateAllFormats();
+					}
+				}
+				else
+					_swfContext = context;				
+			}
+		}
+		
+		/**
+		 * Validate that the lines associated with the flow are internally consistent. 
+		 * @private
+		 * The start of the next line has to match the start of the previous line + the 
+		 * span of the previous line. The last line needs to end at the end of the flow,
+		 * and the first line must be at the start of the text.
+		 */
+		CONFIG::debug public function debugCheckTextFlowLines(validateControllers:Boolean=true):int
+		{
+			var rslt:int = 0;
+			var position:int = 0;
+			var overflow:Boolean = false;
+			for each (var line:TextFlowLine in _lines)
+			{
+				// trace("validateLines:",lines.indexOf(line).toString()," ",line.start," ",line.textLength);
+				rslt += assert(line.absoluteStart == position, "Line start incorrect");
+				rslt += assert(line.textLength >= 0,"Invalind length");
+				if (validateControllers)
+				{
+					var lineController:ContainerController = line.controller;
+					if (lineController != null)
+					{
+						rslt += assert(overflow == false,"non overflow line after overflow line?");
+						rslt += assert(line.absoluteStart >= line.controller.absoluteStart,"bad container mapping");
+						rslt += assert(line.absoluteStart+line.textLength<= lineController.absoluteStart+lineController.textLength,"bad container mapping");
+					}
+					else
+						overflow = true;
+				}
+				position += line.textLength;
+			}
+			return rslt;
+		}		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/FlowDamageType.as b/textLayout_core/src/flashx/textLayout/compose/FlowDamageType.as
new file mode 100755
index 0000000..a70e39a
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/FlowDamageType.as
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	/**
+	 *  The FlowDamageType class is an enumeration class that defines types of damage for damage methods and events.
+	 * When the text content is updated, these changes are reflected in the TextLines after an update. TextLines are 
+	 * marked with a flag that specifies whether or not they are valid, or up to date with all text
+	 * changes. When the text is first updated, all lines are marked valid or static. After the text has been changed,
+	 * and before the next update, lines will be marked with a FlowDamageType that specifies what about the line
+	 * is invalid. Once the update is done, lines will again be marked as valid or static.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class FlowDamageType
+	{
+		/** 
+		 * Value is used to set the <code>validity</code> property if the text content has changed since the
+		 * line was originally created. Invalid lines needs to be recreated before they are used for selection
+		 * or to display the text content changes.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.compose.TextFlowLine#validity	 	 */
+		static public const INVALID:String = "invalid";
+		
+		/**
+		 * Value is used to set the <code>validity</code> property if the line has been invalidated by other lines 
+		 * moving around. For instance, a line above may have been created, so this line needs to be moved down.
+		 * The text line might or might not need recreating at the next compose operation. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.compose.TextFlowLine#validity
+	 	 */
+		static public const GEOMETRY:String = "geometry";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/compose/IFlowComposer.as b/textLayout_core/src/flashx/textLayout/compose/IFlowComposer.as
new file mode 100755
index 0000000..f88d29f
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/IFlowComposer.as
@@ -0,0 +1,498 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flashx.textLayout.compose.ISWFContext;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.compose.TextFlowLine;
+
+	/**
+	 * IFlowComposer defines the interface for managing the layout and display of a text flow.
+	 * 
+	 * <p>Text flows displayed with a flow composer implementation can be dynamic and interactive.
+	 * A flow composer manages one or more display controller. Each controller is associated with
+	 * a display object container (such as a Sprite) through which the lines created for the text
+	 * flow are ultimately displayed. The following diagram illustrates the relationship between TextFlow,
+	 * IFlowComposer, ContainerController, and DisplayObjectContainer objects:</p>
+	 * 
+	 * <p><img src="../../../images/textLayout_singleController.gif" alt="IFlowComposer"></img></p>
+	 *
+	 * <p>A flow composer calculates which portion of a text flow fits in each container and 
+	 * adds the appropriate text lines to the container's display object. The IFlowComposer interface 
+	 * defines separate methods for layout calculations and for updating the display. IFlowComposer also 
+	 * defines methods for incrementally composing and updating a text flow. These methods can be used 
+	 * to avoid blocking the user interface when updating long text flows.</p>
+	 * 
+	 * <p>In addition to managing text composition and display, a flow composer controls which container has focus, 
+	 * manages the display of the selection highlight (which can cross container boundaries), and provides
+	 * direct access to all the TextLine objects in the flow.</p>
+	 * 
+	 * <p>To use an IFlowComposer implementation, assign an instance of that implementation to the
+	 * <code>flowComposer</code> property of a TextFlow object. Call the <code>updateAllControllers()</code>
+	 * method to lay out and display the text in the containers attached to the flow composer.</p>
+	 * 
+	 * <p><b>Note:</b> For simple, static text flows, you can also use the one of the text line factory classes.
+	 * These factory classes will typically create lines with less overhead than a flow composer, but do not
+	 * support editing, dynamic changes, or user interaction.</p>
+	 * 
+	 * @see flashx.textLayout.container.ContainerController ContainerController
+	 * @see FlowComposerBase
+	 * @see StandardFlowComposer
+	 * @see flashx.textLayout.elements.TextFlow TextFlow
+	 * @see flashx.textLayout.factory.StringTextLineFactory StringTextLineFactory
+	 * @see flashx.textLayout.factory.TextFlowTextLineFactory TextFlowTextLineFactory
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface IFlowComposer
+	{
+		/** 
+		 * The root element associated with this IFlowComposer instance. 
+		 * 
+		 * <p>Only a TextFlow object can be a root element.</p>
+		 *  
+		 * @see flashx.textLayout.elements.ContainerFormattedElement ContainerFormattedElement
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 function get rootElement():ContainerFormattedElement;
+		 function setRootElement(newRootElement:ContainerFormattedElement):void;
+			
+		/** 
+		 * The first invalid position in the root element, as an absolute position from the start of the flow.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function get damageAbsoluteStart():int;
+		
+		/** 
+		 * Composes the content of the root element and updates the display.  
+		 *
+		 * <p>Text layout is typically conducted in two phases: composition and display. In the composition phase,
+		 * the flow composer calculates how many lines are necesary to display the content as well as the position of these 
+		 * lines in the flow's display containers. In the display phase, 
+		 * the flow composer updates the display object children of its containers. The <code>updateAllControllers()</code>
+		 * method is expected to carry out both phases. An efficient implementation will keep track of changes to content
+		 * so that a full cycle of composition and display is only performed when necessary.</p>
+		 * 
+		 * <p>This method updates all the text lines and the display list immediately and synchronously.</p>
+		 *
+		 * <p>If the contents of any container is changed, the method must return <code>true</code>.</p>
+		 * 
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+		 */
+		function updateAllControllers():Boolean;
+		
+		/** 
+		 * Composes and updates the display up to and including the container at the specified index.
+		 * 
+		 * <p>The <code>updateToController()</code> method is expected to both compose the content and 
+		 * update the display so that all containers up to and including the container at the specified index are current.
+		 * For example, if you have a chain of twenty containers and specify an index of 10, 
+		 * <code>updateToController()</code> must ensures that the first through the tenth (indexes 0-9) containers
+		 * are composed and displayed. Composition can stop at that point. If <code>controllerIndex</code> 
+		 * is -1 (or not specified), then all containers should be updated.</p>
+		 *
+		 * <p>This method updates all the text lines and the display list immediately and synchronously.</p>
+		 * 
+		 * <p>If the contents of any container is changed, the method must return <code>true</code>.</p>
+		 * 
+		 * @param controllerIndex index of the last container to update, by default will update all containers
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		function updateToController(index:int = int.MAX_VALUE):Boolean;
+		
+		/** 
+		 * Sets the focus to the container that contains the location specified by the <code>absolutePosition</code>
+		 * parameter. 
+		 *
+		 * <p>It is the responsibility of the implementation to define what setting the focus means. For example, an 
+		 * implementation could use the built-in <code>focus</code> property of the Stage object (as long as the
+		 * containers were InteractiveObjects) or the implementation could manage the focus some other way.</p>
+		 * 
+		 * @param absolutePosition Specifies the position in the text flow of the container to receive focus.
+		 * @param preferPrevious If true and the position is the before the first character in a container, sets focus to the end of 
+		 *  the previous container.
+		 * 
+		 * @see flash.display.Stage#focus
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function setFocus(absolutePosition:int,preferPrevious:Boolean=false):void
+
+		/** 
+		 * Calculates how many lines are necessary to display the content in the root element of the flow and the positions of these 
+		 * lines in the flow's display containers.
+		 * 
+		 * <p>Implementations of this method should not update the display, but should save the results so that subsequent
+		 * calls to <code>compose()</code> or <code>updateAllControllers()</code> do not perform an additional recomposition
+		 * if the flow content has not changed.</p>
+		 * 
+		 * <p>If the contents of any container have changed, the method must return <code>true</code>.</p>
+		 * 
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #updateAllControllers()
+	 	 * @see #updateToController()
+		 */
+		 
+		function compose():Boolean;
+		
+		/** 
+		 * Composes the content of the root element up to the specified position.
+		 * 
+		 * <p>If the contents of any container up to and including the container holding the content at the specified
+		 * position has changed, the method returns <code>true</code>. If <code>absolutePosition</code> is greater than the length of the TextFlow 
+		 * (or not specified), then the entire flow is composed.</p>
+		 * 
+		 * @param absolutePosition compose at least up to this position in the TextFlow. By default or if absolutePosition is past the end of the flow compose to the end of the flow.
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #updateAllControllers()
+	 	 * @see #updateToController()
+		 */
+		 
+		function composeToPosition(absolutePosition:int = int.MAX_VALUE):Boolean;
+		
+		/** 
+		 * Composes the content of the root element up to and including the container at the specified index.
+		 * 
+		 * <p>If the contents of any container up to and including the container at the specified
+		 * index has changed, the method returns <code>true</code>. If <code>index</code> is greater than the number of controllers
+		 * (or not specified), then all containers are composed.</p>
+		 * 
+		 * @param controllerIndex compose at least up to this container in the TextFlow. If controllerIndex is greater than the number of controllers, compose to the end of the last container.
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #updateAllControllers()
+	 	 * @see #updateToController()
+		 */
+		 
+		function composeToController(index:int = int.MAX_VALUE):Boolean;
+
+		/** 
+		 * The number of containers assigned to this IFlowComposer instance. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function get numControllers():int;
+		
+		/** 
+		 * Adds a controller to this IFlowComposer instance.
+		 *
+		 * <p>The container is added to the end of the container list.</p>
+		 * 
+		 * @param controller The ContainerController object to add.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		function addController(controller:ContainerController):void;
+		
+		/** 
+		 * Adds a controller to this IFlowComposer instance at the specified index.
+		 *
+		 * <p>The list of controllers is 0-based (the first controller has an index of 0).</p>
+		 * 
+		 * @param controller The ContainerController object to add.
+		 * @param index A numeric index that specifies the position in the controller list at which to insert the ContainerController object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		function addControllerAt(controller:ContainerController, index:int):void;
+		
+		/** 
+		 * Removes a controller from this IFlowComposer instance. 
+		 * 
+		 * @param controller The ContainerController instance to remove.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		function removeController(controller:ContainerController):void;
+		
+		/** 
+		 * Removes the controller at the specified index from this IFlowComposer instance.
+		 *
+		 * @param index The index of the ContainerController object to remove.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		function removeControllerAt(index:int):void
+
+		/** 
+		 * Removes all controllers from this IFlowComposer instance. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function removeAllControllers():void;
+
+		/** 
+		 * Returns the ContainerController object at the specified index. 
+		 * 
+		 * @param index The index of the ContainerController object to return.
+		 * @return 	the ContainerController object at the specified position.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	
+		function getControllerAt(index:int):ContainerController;
+		
+		/** 
+		 * Returns the index of the specified ContainerController object. 
+		 * 
+		 * @param controller A reference to the ContainerController object to find.
+		 * @return the index of the specified ContainerController object or -1 if the controller is not attached to this flow composer.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	
+		function getControllerIndex(controller:ContainerController):int;
+		
+		/** 
+		 * Returns the index of the controller containing the content at the specified position. 
+		 * 
+		 * <p>A position can be considered to be the division between two characters or other elements of a text flow. If 
+		 * the value in <code>absolutePosition</code> is a position between the last character of one 
+		 * container and the first character of the next, then the preceding container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>true</code> and the later container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>false</code>.</p>
+		 *
+		 * <p>The method must return -1 if the content at the specified position is not in any container or is outside
+		 * the range of positions in the text flow.</p>
+		 * 
+		 * @param absolutePosition The position of the content for which the container index is sought.
+		 * @param preferPrevious Specifies which container index to return when the position is between the last element in 
+		 * one container and the first element in the next.
+		 * 
+		 * @return 	the index of the container controller or -1 if not found.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */ 
+	 	 
+		function findControllerIndexAtPosition(absolutePosition:int,preferPrevious:Boolean=false):int;
+
+		/** 
+		 * Returns the sequential line number of the TextFlowLine object that contains the content at the specified position. 
+		 * 
+		 * <p>The number of the first line is 0 and the number of the last line is equal to the number of lines minus one.
+		 * If the position specified in <code>absolutePosition</code> is past the end of the text flow, this method must return
+		 * the number that will be assigned to the next new line added to the text flow (which is equal to the number of current lines).</p>
+		 *
+		 * <p>A position can be considered to be the division between two characters or other elements of a text flow. If 
+		 * the value in <code>absolutePosition</code> is a position between the last line of one 
+		 * container and the first line of the next, then the preceding container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>true</code> and the later container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>false</code>.</p>
+		 * 
+		 * @param absolutePosition	The position of the content for which you want the text line.
+		 * @param preferPrevious Specifies which container index to return when the position is between the last line in 
+		 * one container and the first line in the next.
+		 *
+		 * @return the index of the text line at the specified position. If not found, treats as past the end and returns the
+		 * number of lines.
+		 * 	 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function findLineIndexAtPosition(absolutePosition:int,preferPrevious:Boolean = false):int;
+		
+		/** 
+		* Returns the TextFlowLine object containing the content at the specified position.
+		*
+		* <p>A position can be considered to be the division between two characters or other elements of a text flow. If 
+		* the value in <code>absolutePosition</code> is a position between the last element of one 
+		* line and the first element of the next, then the preceding line is returned if
+		* the <code>preferPrevious</code> parameter is set to <code>true</code> and the later line is returned if
+		* the <code>preferPrevious</code> parameter is set to <code>false</code>.</p>
+		* 
+		* @param absolutePosition	The position of the content for which you want the TextFlowLine object.
+		* @param preferPrevious		Specifies which line to return when the position is between the last element of 
+		* one line and the first element of the next.
+		*
+		* @return	the TextFlowLine containing the content at the specified position, or null if not found.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		function findLineAtPosition(absolutePosition:int,preferPrevious:Boolean = false):TextFlowLine;
+		
+		/** 
+		 * Returns the line with the specified line number. 
+		 *
+		 * <p>The list of lines is numbered from zero to the number of lines minus one. If the value in <code>index</code>
+		 * is outside the bounds of the list of lines, then this function returns <code>null</code>.</p>
+		 * 
+		 * @param index		The line number of the TextFlowLine object to return.
+		 * @return	the TextFlowLine with the specified line number, or <code>null</code>, if not found.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		function getLineAt(index:int):TextFlowLine;
+		
+		/** 
+		 * The total number of lines in the flow. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function get numLines():int;
+		
+		/** 
+		 * Indicates whether any TextFlowLine objects between the beginning of the flow and the line containing the content at 
+		 * the specified position are marked as damaged. 
+		 *
+		 * @param absolutePosition the last position in the area of interest
+		 * @return 	true if any of the TextFlowLine objects from the start of the flow up to the line containing the content at
+		 * <code>absolutePosition</code> are marked as damaged.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function isDamaged(absolutePosition:int):Boolean;
+		
+		
+		/** 
+		 * True, if the flow composer is currently performing a composition operation.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function get composing():Boolean;
+		
+		/** 
+		 * The ISWFContext instance to be used for calls that must be made in a specific SWF context  
+		 * 
+		 * <p>Implementations of IFlowComposer should allow this property to be set so that users
+		 * of the interface can create lines in a different SWF context than the one containing the 
+		 * implementation.  A default implementation of ISWFContext should also be supplied.</p>
+		 * 
+		 * @see flashx.elements.ISWFContext ISWFContext
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		function get swfContext():ISWFContext;
+		function set swfContext(creator:ISWFContext):void;
+		
+		/**
+		 * Called by the TextFlow when the interaction manager changes. 
+		 * 
+		 * <p>Implementations of IFlowComposer should update event listeners and properties
+		 * that reference the interaction manager.</p>
+		 * 
+		 * @param newInteractionManager The new ISelectionManager instance.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		function interactionManagerChanged(newInteractionManager:ISelectionManager):void
+		
+		/** Update the lengths in the lines to maintain mapping to the TextFlow. 
+		 * 
+		 * @param startPosition beginning of change in length
+		 * @param deltaLength change in number of characters.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function updateLengths(startPosition:int,deltaLength:int):void;
+		
+		/** Mark lines as damaged and needing a recompose.
+		 * @param damageStart beginning of range to damage
+		 * @param damageLength number of characters to damage
+		 * @param damageType type of damage.  One of flashx.textLayout.compose.FlowDamageType
+		 * @see flashx.textLayout.compose.FlowDamageType
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function damage(startPosition:int, damageLength:int, damageType:String):void;
+	}
+
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/IParcelList.as b/textLayout_core/src/flashx/textLayout/compose/IParcelList.as
new file mode 100755
index 0000000..c7191ab
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/IParcelList.as
@@ -0,0 +1,150 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.geom.Rectangle;
+	
+	import flashx.textLayout.container.ContainerController;
+		
+	[ExcludeClass]
+	/** @private
+	 * The area inside a text container is sub-divided into smaller areas available for
+	 * text layout. These smaller areas within the container are called Parcels. The 
+	 * ParcelList manages the parcels associated with a TextFlow during composition.
+	 * 
+	 * A container will always have at least one parcel, which corresponds to the container's
+	 * bounding box. If the container has more than one column, each column appears as
+	 * a parcel in the parcel list. If the container has wrap applied, the area around the
+	 * wrap that is available for layout is divided into rectangular-shaped parcels.
+	 * Lastly, parcels may be created during composition for use by flow elements that require
+	 * layout within a specific geometry that may not be the same as the columns: for instance, 
+	 * a straddle head, a table, or a sidehead.
+	 */
+	public interface IParcelList  
+	{
+		/** Initialize the parcel list from the flow composer. The parcel list will
+		 * have the bounding box of the controller(s). If the controller has multiple
+		 * columns, the parcel list will have a parcel for each column. If the 
+		 * controller has wraps, the parcel list may have more parcels to work around
+		 * the wrap areas.
+		 * @param composer	composer we're using
+		 * @param controllerEndIndex	compose through the end of this controller
+		 * @param forceComposeToEnd		force composition to compose all lines of the last controller, even if it's scrollable (will not compose overset text)
+		 */
+		function beginCompose(composer:IFlowComposer, controllerEndIndex:int, forceComposeToEnd:Boolean):void;
+		
+		/** Callback function to notify clients that we're advancing forward to the next parcel. */
+		function get notifyOnParcelChange():Function;
+		function set notifyOnParcelChange(val:Function):void
+		
+		/** Return the left side coordinate of the current parcel.
+		 */
+		function get left():Number;
+		
+		/** Return the right side coordinate of the current parcel.
+		 */
+		function get right():Number;
+		
+		/** Return the top edge coordinate of the current parcel.
+		 */
+		function get top():Number;
+		
+		/** Return the bottom edge coordinate of the current parcel.
+		 */
+		function get bottom():Number;
+		
+		/** Return the width of the current parcel.
+		 */
+		function get width():Number;
+		
+		/** Return the height of the current parcel.
+		 */
+		function get height():Number;
+		
+		/** Returns the column number of the current parcel. */
+		function get columnIndex():int;
+		
+		/** Vertical location within the parcel, as an offset from the top
+		 * of the parcel.
+		 */
+		function get totalDepth():Number;
+		function addTotalDepth(value:Number):Number;
+		
+		/** Return the controller associated with the current parcel.
+		 */
+		function get controller():ContainerController;
+		
+		/** Return the current parcel. Null if we're at the end of the parcel list.
+		 */
+		function get currentParcel():Parcel;
+
+		/** Advance to the next parcel; it will now be the current parcel.
+		 * @return Boolean	false if there is no next parcel.
+		 */
+		function next():Boolean;
+		
+		/** Returns true if the current parcel is the last.
+		 */
+		function atLast():Boolean;
+		
+		/** Returns true if all parcels have been iterated: current parcel is past the last.
+		 */
+		function atEnd():Boolean;
+
+		/** True if the current parcel is at the top of the column */
+		function isColumnStart():Boolean;
+		
+		/** True if we are not wrapping to the composition logical width */
+		function get explicitLineBreaks():Boolean;
+		
+		/** Create a new parcel within the parcel list, for an item with the
+		 * specified geometry. The new parcel is set to the current parcel.
+		 * @param parcel	geometry of the new parcel
+		 * @param blockProgression direction of the text (horizontal or vertical)
+		 * @param verticalJump	true if next parcel goes below this, false if it goes to the right or left
+		 * @return Boolean	true if parcel could be create, false if it doesn't fit
+		 * @see text.formats.BlockProgression
+		 */
+		function createParcel(parcel:Rectangle, blockProgression:String, verticalJump:Boolean):Boolean;
+
+		/** Create a new parcel within the parcel list, for an item with the
+		 * specified geometry. The new parcel is set to the current parcel.
+		 * @param parcel	geometry of the new parcel
+		 * @param blockProgression direction of the text (horizontal or vertical)
+		 * @param verticalJump	true if next parcel goes below this, false if it goes to the right or left
+		 * @return Boolean	true if parcel could be create, false if it doesn't fit
+		 * @see text.formats.BlockProgression
+		 */
+		function createParcelExperimental(parcel:Rectangle, wrapType:String):Boolean;
+
+		/**Return the width for a line that goes at the current vertical location,
+		 * and could extend down for at least height pixels. Note that this function
+		 * can change the current parcel, and the location within the parcel.
+		 * @param height	amount of contiguous vertical space that must be available
+		 * @param minWidth	amount of contiguous horizontal space that must be available 
+		 * @return amount of contiguous horizontal space actually available
+		 */
+		function getLineSlug(slugRect:Rectangle,height:Number, minWidth:Number = 0):Boolean;
+		
+		function getComposeXCoord(slug:Rectangle):Number;
+		function getComposeYCoord(slug:Rectangle):Number;
+		function getComposeWidth(slug:Rectangle):Number;
+		function getComposeHeight(slug:Rectangle):Number;
+	}	//end interface
+} //end package
diff --git a/textLayout_core/src/flashx/textLayout/compose/ISWFContext.as b/textLayout_core/src/flashx/textLayout/compose/ISWFContext.as
new file mode 100755
index 0000000..10c1028
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/ISWFContext.as
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	/** 
+	 * The ISWFContext interface allows a SWF file to share its context with other SWF files that load it.
+	 * An application that loads a SWF file of type ISWFContext can call methods in the context of the loaded SWF file.
+	 * The main usage is for calling the FTE TextLine creation methods.
+	 * 
+	 * <p>There are two reasons for an application to use 
+	 * this interface to control TextLine creation: </p>
+	 * <ul>
+	 *   <li><strong>Reuse an embedded font: </strong> if an application wants to use a font embedded in a loaded SWF file,
+	 * the application can access the font if a TextLine
+	 * is created in the context of the loaded SWF file.</li>
+	 *   <li><strong>Reuse existing TextLine instances</strong>: reusing existing TextLine instances can result in faster recompose times. 
+	 * TLF reuses existing TextLine instances internally. TLF reuses 
+	 * a TextLine by calling <code>TextBlock.recreateTextLine()</code>
+	 * instead of <code>TextBlock.createTextLine()</code> when TLF recognizes that a TextLine is extant.</li>
+	 * </ul>
+	 *
+	 * 
+	 * <p>Your application may have additional TextLine instances that can be reused. 
+	 * To manually reuse existing TextLine instances:</p>
+	 * <ol>
+	 *   <li>trap calls to <code>TextBlock.createTextLine()</code>, then</li>
+	 *   <li>call <code>TextBlock.recreateTextLine()</code> with the extant TextLine instance instead 
+	 * of <code>TextBlock.createTextLine()</code>.</li>
+	 * </ol>
+	 * <p>Please note, however, that the <code>TextBlock.recreateTextLine()</code> is available
+	 * only in Flash Player 10.1 and later.</p>
+	 *
+	 * @see flash.text.engine.TextBlock#createTextLine()
+	 * @see flash.text.engine.TextBlock#recreateTextLine()
+	 * @includeExample examples\EmbeddedFontLineCreator.as -noswf
+	 * @includeExample examples\FontConsumer.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface ISWFContext
+	{
+	    /**
+	     *  A way to call a method in a client controlled context.
+	     *
+	     *  @param fn The function or method to call
+	     *  @param thisArg The this pointer for the function
+	     *  @param argArray The arguments for the function
+	     *  @param returns If true, the function returns a value
+	     *
+	     *  @return Whatever the function returns, if anything.
+	     *
+	     *  @see Function#apply()
+	
+	     *  @langversion 3.0
+	     *  @playerversion Flash 10
+	     *  @playerversion AIR 1.5
+	     */
+	    function callInContext(fn:Function, thisArg:Object, argArray:Array, returns:Boolean=true):*;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/ITextLineCreator.as b/textLayout_core/src/flashx/textLayout/compose/ITextLineCreator.as
new file mode 100755
index 0000000..a6246ed
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/ITextLineCreator.as
@@ -0,0 +1,101 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	
+	/** 
+	 * ITextLineCreator defines an interface for creating TextLine objects for an IFlowComposer instance.
+	 * 
+	 * <p>The ITextLineCreator interface wraps the FTE line creation methods.
+	 * There are basically two reasons why an application might want to use 
+	 * this interface to control the line creation. First,
+	 * if the application has a SWF that contains a font, and you want to 
+	 * use that font from a different SWF, you can reuse the
+	 * font if the TextLine was created from the same SWF that has the font. 
+	 * Second, you can get a faster recompose time by reusing 
+	 * existing TextLines. TLF does that internally, and when it is reusing 
+	 * it will call recreateTextLine instead of createTextLine.
+	 * Your application may have additional TextLines that it knows can be reused. 
+	 * If so, in your implementation of createTextLine,
+	 * you may call TextBlock.recreateTextLine with the line to be reused instead 
+	 * of TextBlock.createTextLine.</p>
+	 *
+	 * @see flast.text.engine.TextLine
+	 * @see flashx.textLayout.compose.IFlowComposer
+	 * @see flashx.textLayout.elements.TextFlow TextFlow
+	 * 
+	 * @includeExample examples\ITextLineCreator_ClassExample.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface ITextLineCreator
+	{
+		/** 
+		 * Creates a TextLine object for a flow composer.
+		 * 
+		 * <p>Called by a flow composer when a text line must be created.</p>
+		 * 
+		 * @param textBlock The TextBlock object for which the line is to be created.
+		 * @param previousLine The previous line created for the TextBlock, if any.
+		 * @param width The maximum width of the line.
+		 * @param lineOffset An optional offset value.
+		 * @param fitSomething If <code>true</code>, at least one character or inline graphic must be fit on the line
+		 * even if that element causes the line to exceed the value in the <code>width</code> parameter.
+		 * 
+		 * @return TextLine the created TextLine object
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		function createTextLine(textBlock:TextBlock, previousLine:TextLine = null, width:Number = 1000000, lineOffset:Number = 0.0, fitSomething:Boolean = false):TextLine
+
+		/** 
+		 * Recreates a TextLine object for a flow composer.
+		 * 
+		 * <p>Called by a flow composer when a text line must be recreated.</p>
+		 * 
+		 * <p><b>Note:</b> The TextBlock <code>recreateTextLine()</code> method is available starting in
+		 * Flash Player 10.1 and AIR 2.0. To implement this method so that it is compatible with
+		 * earlier runtimes, test for the existence of the <code>recreateTextLine()</code> method 
+		 * on the TextBlock object before calling it.</p>
+		 *  
+		 * @param textBlock The TextBlock object for which the line is to be created.
+		 * @param previousLine The previous line created for the TextBlock, if any.
+		 * @param width The maximum width of the line.
+		 * @param lineOffset An optional offset value.
+		 * @param fitSomething If <code>true</code>, at least one character or inline graphic must be fit on the line
+		 * even if that element causes the line to exceed the value in the <code>width</code> parameter.
+		 * 
+		 * @return TextLine the recreated TextLine object
+		 * 
+		 * @includeExample examples\ITextLineCreator_recreateTextLine.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		function recreateTextLine(textBlock:TextBlock, textLine:TextLine, previousLine:TextLine = null, width:Number = 1000000, lineOffset:Number = 0.0, fitSomething:Boolean = false):TextLine
+
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/compose/IVerticalJustificationLine.as b/textLayout_core/src/flashx/textLayout/compose/IVerticalJustificationLine.as
new file mode 100755
index 0000000..6ca2b59
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/IVerticalJustificationLine.as
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+	
+	/** 
+	 * The IVerticalJustificationLine interface defines the methods and properties required to allow
+	 * the vertical justification of text lines.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public interface IVerticalJustificationLine
+	{
+		/** 
+		 * The horizontal position of the line relative to its container, expressed as the offset in pixels from the 
+		 * left of the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #y
+		 */
+		function get x():Number;
+		
+		/** Set X location for the line.  Used only during vertical justification. @private */
+		function set x(val:Number):void;
+		
+		/** 
+		 * The vertical position of the line relative to its container, expressed as the offset in pixels from the top 
+		 * of the container.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see #x
+		 */
+		function get y():Number;
+		
+		/** Set Y location for the line.  Used only during vertical justification. @private */
+		function set y(val:Number):void;
+		
+		/** 
+		 * @copy flash.text.engine.TextLine#ascent
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function get ascent():Number;
+		
+		/** 
+		 * @copy flash.text.engine.TextLine#descent
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function get descent():Number;
+		
+		/** The height of the line in pixels.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		function get height():Number;
+	}
+
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/Parcel.as b/textLayout_core/src/flashx/textLayout/compose/Parcel.as
new file mode 100755
index 0000000..f9a6266
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/Parcel.as
@@ -0,0 +1,114 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.geom.Rectangle;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+		
+	[ExcludeClass]
+	/** Helper class for implementations of IParcelList
+	 * 
+	 * @private
+	 */
+	public class Parcel extends Rectangle
+	{
+		public static const TOP_OF_COLUMN:int = 1;
+		public static const BOT_OF_COLUMN:int = 2;
+		public static const FULL_COLUMN:int = 3;
+		
+		/** Constructor. */
+		public function Parcel(x:Number, y:Number, width:Number, height:Number, cont:ContainerController, col:int, colCoverage:int)
+		{
+			super(x,y,width,height);
+			_controller   = cont;
+			_column       =  col;
+			_columnCoverage = colCoverage;
+			_fitAny	  = false;
+			_composeToPosition = false;
+		}
+		
+		public function initialize(x:Number, y:Number, width:Number, height:Number, cont:ContainerController, col:int, colCoverage:int):Parcel
+		{
+			this.x = x;
+			this.y = y;
+			this.width = width;
+			this.height = height;
+			
+			_controller   = cont;
+			_column       =  col;
+			_columnCoverage = colCoverage;
+			_fitAny	  = false;
+			_composeToPosition = false;
+			
+			return this;
+		}
+		
+		private var _controller:ContainerController;
+		private var _columnCoverage:int;
+		private var _column:int;
+		private var _fitAny:Boolean;
+		private var _composeToPosition:Boolean;
+		
+		/** prevent any leaks. @private */
+		tlf_internal function releaseAnyReferences():void
+		{
+			_controller = null;
+		}
+		
+		public function replaceBounds(r:Rectangle):void
+		{
+			this.x = r.x;
+			this.y = r.y;
+			this.width = r.width;
+			this.height = r.height;
+		}
+		
+		public function get controller():ContainerController
+		{ return _controller; }
+
+		public function get topOfColumn():Boolean
+		{ return (_columnCoverage&TOP_OF_COLUMN) == TOP_OF_COLUMN; }
+		/** describes how this parcel covers its source column */
+		public function get columnCoverage():int
+		{ return _columnCoverage; }
+		public function set columnCoverage(val:int):void
+		{ _columnCoverage = val; }
+		/** column number in the container */
+		public function get column():int
+		{ return _column; }
+		public function get fitAny():Boolean
+		{ return _fitAny; }
+		public function set fitAny(value:Boolean):void
+		{ _fitAny = value; }
+		public function get composeToPosition():Boolean
+		{ return _composeToPosition; }
+		public function set composeToPosition(value:Boolean):void
+		{ _composeToPosition = value; }
+		/** Do explicit line breaking (no wrapping) */
+		public function get measureWidth():Boolean
+		{ return controller.measureWidth; }
+		public function get measureHeight():Boolean
+		{ return controller.measureHeight; }
+
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/compose/ParcelList.as b/textLayout_core/src/flashx/textLayout/compose/ParcelList.as
new file mode 100755
index 0000000..7257392
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/ParcelList.as
@@ -0,0 +1,509 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.container.ColumnState;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.formats.VerticalAlign;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+			
+	[ExcludeClass]
+	/** @private
+	 * Implementation of IParcelList used for composing text containers that have single
+	 * column, no wraps, and no floats.
+	 * 
+	 * ParcelList will always have one parcel, which corresponds to the container's
+	 * bounding box. 
+	 */
+	public class ParcelList implements IParcelList  
+	{
+		protected var _flowComposer:IFlowComposer;
+		
+		/** Current vertical position in the parcel. */
+		protected var _totalDepth:Number;
+		
+		/** whether the current parcel has any content */
+		protected var _hasContent:Boolean;
+		
+		/** The list of parcels that are available for text layout.
+			They are appear in the array in reading order: the first text goes in the
+			first parcel, when it gets filled later text is flowed into the second 
+			parcel, and so on.  */
+		private var _parcelArray:Array;	/* of Parcel */
+		private var _numParcels:int;
+		private var _singleParcel:Parcel;
+		
+		/** Index of the "current" parcel. These next two variables must be kept in sync. */
+		protected var _currentParcelIndex:int;
+		protected var _currentParcel:Parcel;
+		
+		/** Callback to notify that we're going to the next parcel */
+		protected var _notifyOnParcelChange:Function;
+		
+		/** Column number of the current parcel */
+		private var _columnIndex:int;
+		private var _columnController:ContainerController;
+		
+		private var _explicitLineBreaks:Boolean;
+		
+		/** true if we should include the last line if any part of it fits */
+	//	protected var _includePartialLine:Boolean;
+		
+		
+	//	private var parcel:Parcel;
+	
+		private static const MAX_HEIGHT:Number = 900000000;		// vertical scroll max - capped to prevent loss of precision - what should it be?
+		private static const MAX_WIDTH:Number =  900000000;		// horizontal scroll max - capped to prevent loss of precision - what should it be?
+
+			/** minimum allowable width of a line */
+			
+		/** Writing mode for vertical, left to right and left to right. @see text.formats.BlockProgression */
+		protected var _blockProgression:String;
+		
+		// a single parcellist that is checked out and checked in
+		static private var _sharedParcelList:ParcelList;
+
+		/** @private */
+		static tlf_internal function getParcelList():ParcelList
+		{
+			var rslt:ParcelList = _sharedParcelList ? _sharedParcelList : new ParcelList();
+			_sharedParcelList = null;
+			return rslt;
+		}
+		
+		/** @private */
+		static tlf_internal function releaseParcelList(list:IParcelList):void
+		{
+			if (_sharedParcelList == null)
+			{
+				_sharedParcelList = list as ParcelList;
+				if (_sharedParcelList)
+					_sharedParcelList.releaseAnyReferences();
+			}
+		}
+
+		/** Constructor. */
+		public function ParcelList()
+		{ _numParcels = 0;	}
+		
+		/** prevent any leaks. @private */
+		tlf_internal function releaseAnyReferences():void
+		{
+			this._flowComposer = null;
+			this._columnController = null;
+			
+			_numParcels = 0;
+			_parcelArray = null;
+			
+			if (_singleParcel)
+				_singleParcel.releaseAnyReferences();
+		}
+		
+		CONFIG::debug public function getBounds():Array
+		{
+			var boundsArray:Array = [];
+			for (var i:int = 0; i < _numParcels; ++i)
+				boundsArray.push(getParcelAtIndex(i));
+			return boundsArray;
+		}
+		
+		protected function get numParcels():int
+		{ return _numParcels; }
+		
+		protected function getParcelAtIndex(idx:int):Parcel
+		{ return _numParcels == 1 ? _singleParcel : _parcelArray[idx]; }
+		
+		protected function insertParcel(startIdx:int, parcel:Parcel):void
+		{
+			if (_numParcels == 0)
+				_singleParcel = parcel;
+			else
+			{
+				if (_numParcels == 1)
+					_parcelArray = [ _singleParcel ];
+				_parcelArray.splice(startIdx, 0, parcel);
+			}
+			_numParcels++;
+		}
+		
+		protected function set parcels(newParcels:Array):void
+		{
+			_numParcels = newParcels.length;
+			if (_numParcels == 0)
+				_parcelArray = null;
+			else if (_numParcels == 1)
+			{
+				_parcelArray = null;
+				_singleParcel = newParcels[0];
+			}
+			else
+				_parcelArray = newParcels;
+		}
+		
+		public function get left():Number
+		{
+			return _currentParcel.left;
+		}
+		
+		public function get right():Number
+		{
+			return _currentParcel.right;
+		}
+		
+		public function get top():Number
+		{
+			return _currentParcel.top;
+		}
+		
+		public function get bottom():Number
+		{
+			return _currentParcel.bottom;
+		}
+		
+		public function get width():Number
+		{
+			return _currentParcel.width;
+		}
+		
+		public function get height():Number
+		{
+			return _currentParcel.height;
+		}
+		
+		public function get fitAny():Boolean
+		{
+			return _currentParcel.fitAny;
+		}
+				
+		public function get controller():ContainerController
+		{
+			return _columnController;
+		}
+		
+		public function get columnIndex():int
+		{ return _columnIndex; }
+		
+		public function get explicitLineBreaks():Boolean
+		{ 
+			return _explicitLineBreaks;
+		}
+		
+		private function get measureWidth():Boolean
+		{
+			if (_explicitLineBreaks)
+				return true;
+			if (!_currentParcel)
+				return false;
+			if (_blockProgression == BlockProgression.TB)
+				return _currentParcel.measureWidth;
+			else
+				return _currentParcel.measureHeight;
+		}
+
+		private function get measureHeight():Boolean
+		{
+			if (!_currentParcel)
+				return false;
+			if (_blockProgression == BlockProgression.TB)
+				return _currentParcel.measureHeight;
+			else
+				return _currentParcel.measureWidth;
+		}
+		
+		public function get totalDepth():Number
+		{
+			return _totalDepth;
+		}
+		
+		public function get notifyOnParcelChange():Function
+		{
+			return _notifyOnParcelChange;
+		}
+		
+		public function set notifyOnParcelChange(val:Function):void
+		{
+			_notifyOnParcelChange = val;
+		}
+		
+		public function addTotalDepth(value:Number):Number
+		{
+			_hasContent = true;
+			_totalDepth += value;	
+		//	trace("addTotalDepth", value, "newDepth", totalDepth);
+			return _totalDepth;
+		}
+		
+		protected function reset():void
+		{
+			_totalDepth = 0;
+			_hasContent = false;
+			_columnIndex = 0;
+			_currentParcelIndex = 0;
+			
+			if (_numParcels != 0)
+			{
+				_currentParcel    = getParcelAtIndex(_currentParcelIndex);
+				_columnController =  _currentParcel.controller;
+				_columnIndex      = 0;
+			}
+			else
+			{
+				_currentParcel = null;
+				_columnController =  null;
+				_columnIndex = -1;
+			}
+		}
+		
+		private function addParcel(column:Rectangle, cont:ContainerController, col:int, colCoverage:int):void
+		{
+			var newParcel:Parcel = _numParcels == 0 && _singleParcel 
+				? _singleParcel.initialize(column.x,column.y,column.width,column.height,cont,col,colCoverage) 
+				: new Parcel(column.x, column.y, column.width, column.height, cont, col, colCoverage)
+			if (_numParcels == 0)
+				_singleParcel = newParcel;
+			else if (numParcels == 1)
+				_parcelArray = [  _singleParcel, newParcel ];
+			else
+				_parcelArray.push(newParcel);
+			_numParcels++;
+		}
+		
+		protected function addOneControllerToParcelList(controllerToInitialize:ContainerController):void
+		{
+			// Initialize new parcels for columns
+			var columnState:ColumnState = controllerToInitialize.columnState;
+			for (var columnIndex:int = 0; columnIndex < columnState.columnCount; columnIndex++)
+			{
+				var column:Rectangle = columnState.getColumnAt(columnIndex);
+				if (!column.isEmpty())
+					addParcel(column, controllerToInitialize, columnIndex, Parcel.FULL_COLUMN);
+			}
+		}
+		
+		public function beginCompose(composer:IFlowComposer, controllerEndIndex:int, composeToPosition:Boolean):void
+		{
+			_flowComposer = composer;
+			
+			var rootFormat:ITextLayoutFormat = composer.rootElement.computedFormat;
+			_explicitLineBreaks = rootFormat.lineBreak == LineBreak.EXPLICIT;
+			_blockProgression   = rootFormat.blockProgression;
+			
+			if (composer.numControllers != 0)
+			{
+				// if controllerEndIndex is not specified then assume we are composing to position and add all controllers
+				if (controllerEndIndex < 0)
+					controllerEndIndex = composer.numControllers-1;
+				else
+					controllerEndIndex = Math.min(controllerEndIndex,composer.numControllers-1);
+				var idx:int = 0;
+				do
+				{
+					addOneControllerToParcelList(ContainerController(composer.getControllerAt(idx)));
+				} while (idx++ != controllerEndIndex)
+				// adjust the last container for scrolling
+				if (controllerEndIndex == composer.numControllers-1)
+					adjustForScroll(ContainerController(ContainerController(composer.getControllerAt(composer.numControllers-1))), composeToPosition);
+			}
+			reset();
+		}
+		
+		/** Adjust the size of the parcel corresponding to the last column of the containter, in 
+		 * order to account for scrolling.
+		 */
+		private function adjustForScroll(containerToInitialize:ContainerController, composeToPosition:Boolean):void
+		{			
+			// Expand the last parcel if scrolling could be enabled. Expand to twice what would fit in available space. 
+			// We will start composing from the top, so if we've scrolled down there will be more to compose.
+			// We turn on fitAny, so that lines will be included in the container even if only a tiny portion of the line
+			// fits. This makes lines that are only partially scrolling in appear. We turn on composeToPosition if we're
+			// forcing composition to go through a given position -- this will make all lines fit, and composition will
+			// continue until it is past the supplied position.
+			if (_blockProgression != BlockProgression.RL)
+			{
+				if (containerToInitialize.verticalScrollPolicy != ScrollPolicy.OFF)
+				{
+					var p:Parcel = getParcelAtIndex(_numParcels-1);
+					if (p)
+					{
+						var verticalPaddingAmount:Number = containerToInitialize.effectivePaddingBottom + containerToInitialize.effectivePaddingTop;
+						p.bottom = containerToInitialize.verticalScrollPosition + p.height + verticalPaddingAmount;
+						p.fitAny = true;
+						p.composeToPosition = composeToPosition;
+					}
+				}
+			}
+			else	// vertical text case
+			{
+				if (containerToInitialize.horizontalScrollPolicy != ScrollPolicy.OFF)
+				{
+					p = getParcelAtIndex(_numParcels-1);
+					if (p)
+					{
+						var horizontalPaddingAmount:Number = containerToInitialize.effectivePaddingRight + containerToInitialize.effectivePaddingLeft;
+						p.left = containerToInitialize.horizontalScrollPosition - p.width - horizontalPaddingAmount;
+						p.fitAny = true;
+						p.composeToPosition = composeToPosition;
+					}
+				}
+			}
+		}
+
+		public		function getComposeXCoord(o:Rectangle):Number
+		{ 
+			// trace("LPL: getComposeXCoord");
+			return _blockProgression == BlockProgression.RL ? o.right : o.left;
+		}
+		public		function getComposeYCoord(o:Rectangle):Number
+		{ 
+			// trace("LPL: getComposeYCoord");
+			return o.top;
+		}
+
+		public function getComposeWidth(o:Rectangle):Number
+		{ 
+			// trace("LPL: getComposeWidth");
+			if (measureWidth)
+				return TextLine.MAX_LINE_WIDTH;
+			return _blockProgression == BlockProgression.RL ? o.height : o.width; 
+		}
+		public function getComposeHeight(o:Rectangle):Number
+		{ 
+			// trace("LPL: getComposeHeight");
+			if (measureHeight)
+				return TextLine.MAX_LINE_WIDTH;
+			return _blockProgression == BlockProgression.RL ? o.width : o.height; 
+		}		
+		/** True if the current parcel is at the top of the column */
+		public function isColumnStart():Boolean
+		{
+			return (!_hasContent && _currentParcel.topOfColumn);
+		}
+		
+		/** Returns true if the current parcel is the last.
+		*/
+		public function atLast():Boolean
+		{
+			return _numParcels == 0 || _currentParcelIndex == _numParcels -1;
+		}
+		
+		public function atEnd():Boolean
+		{
+			return _numParcels == 0 || _currentParcelIndex >= _numParcels;
+		}
+		
+		public function next():Boolean
+		{
+			CONFIG::debug { assert(_currentParcelIndex >= 0 && _currentParcelIndex < _numParcels, "invalid _currentParcelIndex in ParcelList"); }			
+			var nextParcelIsValid:Boolean = (_currentParcelIndex + 1) < _numParcels;
+
+			_notifyOnParcelChange(nextParcelIsValid ? getParcelAtIndex(_currentParcelIndex + 1) : null)
+			
+			_currentParcelIndex += 1;
+			_totalDepth = 0;
+			_hasContent = false;
+			
+			if (nextParcelIsValid)
+			{
+				_currentParcel = getParcelAtIndex(_currentParcelIndex);
+				var nextController:ContainerController = _currentParcel.controller;
+				if (nextController == _columnController)
+					_columnIndex++;
+				else
+				{
+					_columnIndex = 0;
+					_columnController = nextController;
+				}
+			}
+			else
+			{
+				_currentParcel = null;
+				_columnIndex = -1;
+				_columnController = null;
+			}
+	
+			return nextParcelIsValid;
+		}
+		
+		public function createParcel(parcel:Rectangle, blockProgression:String, verticalJump:Boolean):Boolean
+			// If we can get the requested parcel to fit, create it in the parcels list
+		{
+			return false;
+		}
+		
+		public function createParcelExperimental(parcel:Rectangle, wrapType:String):Boolean
+			// If we can get the requested parcel to fit, create it in the parcels list
+		{
+			return false;
+		}
+		
+		public function get currentParcel():Parcel
+		{ return _currentParcel; }
+
+		/**Return the width for a line that goes at the current vertical location,
+		 * and could extend down for at least height pixels. Note that this function
+		 * can change the current parcel, and the location within the parcel.
+		 * @param height	amount of contiguous vertical space that must be available
+		 * @param minWidth	amount of contiguous horizontal space that must be available 
+		 * @return amount of contiguous horizontal space actually available
+		 */
+		public function getLineSlug(slugRect:Rectangle, height:Number, minWidth:Number = 0):Boolean
+		{
+			// trace("getLineSlug",slugRect,height,minWidth);
+			if (_currentParcelIndex < _numParcels) 
+			{
+				var tileWidth:Number = getComposeWidth(_currentParcel);
+				if (tileWidth > minWidth)
+				{
+					// Fit the line if any part of the line fits in the height. Observe the cast to int!
+					if (currentParcel.composeToPosition || _totalDepth + (_currentParcel.fitAny ? 1 : int(height)) <= getComposeHeight(_currentParcel))
+					{
+						if (_blockProgression != BlockProgression.RL)
+						{
+							slugRect.x = left;
+							slugRect.y = _currentParcel.top + _totalDepth;
+							slugRect.width = tileWidth;
+							slugRect.height = height;
+						}
+						else
+						{
+							slugRect.x = left;
+							slugRect.y = _currentParcel.top;
+							slugRect.width = _currentParcel.width-_totalDepth;
+							slugRect.height = tileWidth;
+						}
+						return true;
+					}
+				}
+			} 
+			return false;
+		}
+	
+
+	}	//end class
+} //end package
diff --git a/textLayout_core/src/flashx/textLayout/compose/SimpleCompose.as b/textLayout_core/src/flashx/textLayout/compose/SimpleCompose.as
new file mode 100755
index 0000000..7368c05
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/SimpleCompose.as
@@ -0,0 +1,372 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.events.Event;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.OverflowPolicy;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextFlowLineLocation;
+	import flashx.textLayout.formats.BaselineOffset;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextAlign;
+	import flashx.textLayout.formats.VerticalAlign;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** Keeps track of internal state during composition. 
+	 * 
+	 * This is the simpler version, used when there are no floats, no wraps, no columns.
+	 * @private
+	 */
+	public class SimpleCompose extends BaseCompose
+	{
+		// reusable scratch TextFlowLine
+		protected var workingLine:TextFlowLine = new TextFlowLine(null, null);
+		
+		// resulting TextLines
+		public var _lines:Array;
+		
+		// scratch aligns for VJ
+		private var _vjLines:Array;
+		
+		// for figuring out when to do VJ
+		private var vjBeginLineIndex:int = 0;
+		private var vjDisableThisParcel:Boolean = false;
+		private var vjParcel:Parcel;
+		private var vjType:String;
+		
+		// accumulator for absolute start computation to support truncation 
+		private var _totalLength:Number;
+		
+		/** Constructor. */
+		public function  SimpleCompose()
+		{	
+			super();
+			_lines = new Array();
+			_vjLines = new Array();
+		}
+		
+		/** @private */
+		protected override function createParcelList():IParcelList
+		{
+			return ParcelList.getParcelList();
+		}
+		/** @private */
+		protected override function releaseParcelList(list:IParcelList):void
+		{
+			ParcelList.releaseParcelList(list);
+		}	
+
+		protected override function  initializeForComposer(composer:IFlowComposer, composeToPosition:int, controllerEndIndex:int):void
+		{
+			super.initializeForComposer(composer, composeToPosition, controllerEndIndex);
+			
+			// vj support
+			_vjLines.splice(0);
+			vjBeginLineIndex = 0;
+			vjParcel = parcelList.currentParcel;	
+			vjDisableThisParcel = false;
+			vjType = vjParcel ? vjParcel.controller.computedFormat.verticalAlign : VerticalAlign.TOP;
+			
+			_startController = composer.getControllerAt(0);
+            _startComposePosition = 0;
+		}
+
+		/** @private */
+		public override function composeTextFlow(textFlow:TextFlow, composeToPosition:int, controllerEndIndex:int):int
+		{
+			_flowComposer = textFlow.flowComposer as StandardFlowComposer;
+			
+			// empty out lines array
+			_lines.splice(0);
+			
+			// accumulator initialization
+			_totalLength = 0;
+			
+			return super.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+		}
+		
+ 		override protected function doVerticalAlignment(canVerticalAlign:Boolean,nextParcel:Parcel):Boolean
+ 		{
+			var result:Boolean = false;
+
+			if (canVerticalAlign && vjType != VerticalAlign.TOP && vjBeginLineIndex != _lines.length &&  !vjDisableThisParcel && vjParcel.columnCoverage == Parcel.FULL_COLUMN)
+			{						
+				applyVerticalAlignmentToColumn(vjParcel.controller,vjType,_vjLines,0,_vjLines.length);
+				result = true;	// lines were moved
+			}
+
+			_vjLines.splice(0);
+			vjBeginLineIndex = _lines.length;
+			vjParcel = nextParcel;	// next parcel
+			vjDisableThisParcel = false;
+			if (nextParcel)
+				vjType = vjParcel.controller.computedFormat.verticalAlign;
+			return result;
+ 		}
+ 		
+		private function finalizeLine(curLine:TextFlowLine):void
+		{
+			var line:TextLine = curLine.createShape(_blockProgression);
+			
+			if (textFlow.backgroundManager)
+				textFlow.backgroundManager.finalizeLine(curLine);
+				
+			line.userData = _totalLength; 		// store absolute start position in the userData field
+			_totalLength += line.rawTextLength; // update length accumulator
+			_lines.push(line);
+			if (vjType != VerticalAlign.TOP)
+				_vjLines.push(new VJHelper(line,curLine.height));
+				
+			commitLastLineState (curLine);	
+		}
+
+		public function get textFlow():TextFlow
+		{
+			return _textFlow;
+		}
+		
+		/** @private */
+		protected override function composeParagraphElement(elem:ParagraphElement, absStart:int):Boolean
+		{
+			_curParaElement  = elem;
+			_curParaStart    = absStart;
+			_curParaFormat = elem.computedFormat;
+			CONFIG::debug { assert(_curParaStart == elem.getAbsoluteStart(),"composeParagraphElement: bad start"); }
+			_curElement 	 = elem.getFirstLeaf();
+			_curElementStart = _curParaStart;
+			return composeParagraphElementIntoLines();
+		}		
+		/** @private */
+		protected override function composeNextLine():TextFlowLine
+		{
+			// Check to see if there's an existing line that is composed up-to-date
+
+			var startCompose:int = _curElementStart + _curElementOffset - _curParaStart;
+			var prevLine:TextLine = startCompose != 0 ? workingLine.getTextLine() : null;
+			CONFIG::debug { assert(!prevLine || prevLine.validity == "valid","Bad prevline: "+Debugging.getIdentity(prevLine)); }
+			var finishLineSlug:Rectangle = _parcelList.currentParcel;
+			var curLine:TextFlowLine;
+			
+			for (;;) 
+			{
+				for (;;)
+				{	
+					// generate new line
+					CONFIG::debug { assert(!_parcelList.atEnd(), "failing to stop"); }
+					CONFIG::debug { assert(_curElement is FlowLeafElement, "element must be leaf before calling composeLine"); }
+					
+					curLine = createTextLine(prevLine,	startCompose, _parcelList.getComposeXCoord(finishLineSlug), _parcelList.getComposeYCoord(finishLineSlug),	_parcelList.getComposeWidth(finishLineSlug));
+					if (curLine != null)
+						break;
+					// force advance to the next parcel
+					if (!_parcelList.next())
+						return null;
+				}
+				
+				// updates _lineSlug
+				curLine = fitLineToParcel(curLine, true);
+				if (curLine)
+					break;
+				if (_parcelList.atEnd())
+					return null;
+				finishLineSlug = _lineSlug;
+			}
+			
+			finalizeLine(curLine);
+
+			CONFIG::debug { assert(curLine != null, "curLine != null"); }			
+			return curLine;
+		}
+
+		/** @private */
+		protected function createTextLine(prevLine:TextLine,	// previous line
+			lineStart:int, 		// text index of position to start from, relative to start of paragraph
+			x:Number,			// left edge of the line
+			y:Number, 			// top of the line
+			targetWidth:Number	// target width we're composing into
+			):TextFlowLine
+        {     		    		
+			// adjust target width for text indent, start and end indent 			
+ 			var lineOffset:Number = Number(_curParaFormat.paragraphStartIndent);  	// indent to "beginning" of the line.  Direction dependent (as is paragraphStartIndent)    		
+     		if (prevLine == null) 	// first line indent
+     			lineOffset += Number(_curParaFormat.textIndent);
+     		
+     		var outerTargetWidth:Number = targetWidth;
+     		targetWidth -= (Number(_curParaFormat.paragraphEndIndent) + lineOffset);		// make room for offset and end indent
+     		targetWidth = (targetWidth < 0) ? 0 : targetWidth;		// no negative targetwidth allowed
+     		if (targetWidth > TextLine.MAX_LINE_WIDTH)
+     			targetWidth = TextLine.MAX_LINE_WIDTH;
+	   		
+        	//var textLine:TextLine = _flowComposer.textLineCreator.createTextLine(_curParaElement.getTextBlock(), prevLine, targetWidth, lineOffset, true);
+        	var textLine:TextLine = TextLineRecycler.getLineForReuse();
+        	var textBlock:TextBlock = _curParaElement.getTextBlock();
+	   		if (textLine)
+	   		{
+	   			CONFIG::debug { assert(_textFlow.backgroundManager == null || _textFlow.backgroundManager.lineDict[textLine] === undefined,"Bad TextLine in recycler cache"); }
+	        	textLine = swfContext.callInContext(textBlock["recreateTextLine"], textBlock, [ textLine, prevLine, targetWidth, lineOffset, true ]);
+      		}
+	   		else
+	   		{
+	        	textLine = swfContext.callInContext(textBlock.createTextLine, textBlock, [prevLine, targetWidth, lineOffset, true ]);
+      		}
+        	// Unable to fit a new line
+        	if (textLine == null)
+        		return null;
+
+ 			CONFIG::debug { assert(_curParaStart == _curParaElement.getAbsoluteStart(),"bad _curParaStart"); }
+ 			workingLine.initialize(_curParaElement, outerTargetWidth, lineOffset, lineStart + _curParaStart, textLine.rawTextLength, textLine);
+ 			CONFIG::debug { assert(workingLine.targetWidth == targetWidth,"Bad targetWidth"); }
+ 			
+			// update spaceBefore & spaceAfter		
+			var linePos:uint = workingLine.location;
+			workingLine.setSpaceBefore((linePos & TextFlowLineLocation.FIRST) ? Number(_curParaFormat.paragraphSpaceBefore) : 0);
+			workingLine.setSpaceAfter((linePos & TextFlowLineLocation.LAST) ? Number(_curParaFormat.paragraphSpaceAfter) : 0); 
+
+ 			return workingLine;
+        }
+        
+        /** @private */
+        tlf_internal function swapLines(lines:Array):Array
+        {
+        	var current:Array = _lines;
+        	_lines = lines;
+        	return current;
+        }
+
+		/** Final adjustment on the content bounds. */
+ 		override protected function finalParcelAdjustment(controller:ContainerController):void
+ 		{
+ 			var minX:Number = TextLine.MAX_LINE_WIDTH;
+ 			var minY:Number = TextLine.MAX_LINE_WIDTH;
+ 			var maxX:Number = -TextLine.MAX_LINE_WIDTH;
+ 			var maxY:Number = -TextLine.MAX_LINE_WIDTH;
+ 			
+ 			var textLine:TextLine;
+ 			var verticalText:Boolean = _blockProgression == BlockProgression.RL;
+ 			var startPos:int = controller.absoluteStart;
+
+			for each (textLine in _lines)
+			{
+				var leaf:FlowLeafElement = controller.textFlow.findLeaf(startPos);
+				var para:ParagraphElement = leaf.getParagraph();
+
+            	// Check the logical vertical dimension first
+            	// If the lines have children, they may be inlines. The origin of the TextLine is the baseline, 
+            	// which does not include the ascent of the inlines or the text. So we have to factor that in.
+				// var verticalAdjust:Number = verticalText ? textLine.descent : textLine.ascent;
+				var inlineAscent:Number = 0;
+				if (textLine.numChildren > 0)		// adjustjust logical vertical coord to take into account inlines
+				{
+					var leafStart:int = leaf.getAbsoluteStart();
+					inlineAscent = TextFlowLine.getTextLineTypographicAscent(textLine, leaf, leafStart, startPos + textLine.rawTextLength, para);
+				}
+
+				// Figure out the logical horizontal adjustment
+				var edgeAdjust:Number = 0;
+				var curParaFormat:ITextLayoutFormat = para.computedFormat;
+				if (curParaFormat.direction == Direction.LTR)
+					edgeAdjust = curParaFormat.paragraphStartIndent + Math.max(curParaFormat.textIndent, 0);
+				else
+					edgeAdjust = curParaFormat.paragraphEndIndent;
+				
+				if (verticalText)
+				{
+		            minX = Math.min(textLine.x - textLine.descent, minX);
+		            maxX = Math.max(textLine.x + Math.max(inlineAscent,textLine.ascent), maxX);
+		           	minY = Math.min(textLine.y - edgeAdjust, minY);
+				}
+				else
+				{
+					if (inlineAscent < textLine.ascent)
+						inlineAscent = textLine.ascent;
+		            minX = Math.min(textLine.x - edgeAdjust, minX);
+		           	minY = Math.min(textLine.y - inlineAscent, minY);
+		  		}
+		  		startPos += textLine.rawTextLength;
+   			}
+            // Don't make adjustments for tiny fractional values.
+            if (minX != TextLine.MAX_LINE_WIDTH && Math.abs(minX-_parcelLeft) >= 1)
+         		_parcelLeft = minX;
+            if (maxX != -TextLine.MAX_LINE_WIDTH && Math.abs(maxX-_parcelRight) >= 1)
+         		_parcelRight = maxX;
+         	if (minY != TextLine.MAX_LINE_WIDTH && Math.abs(minY-_parcelTop) >= 1)
+           		_parcelTop = minY;
+         	if (maxY != -TextLine.MAX_LINE_WIDTH && Math.abs(maxY-_parcelBottom) >= 1)
+           		_parcelBottom = maxY;
+ 		}		
+		
+		tlf_internal override function releaseAnyReferences():void
+		{
+			super.releaseAnyReferences();
+			workingLine.initialize(null,0,0,0,0,null);
+			// parcelList.releaseAnyReferences();
+		}
+	}
+}
+import flash.text.engine.TextLine;
+import flashx.textLayout.compose.IVerticalJustificationLine;
+import flash.text.engine.TextLineCreationResult;
+
+class VJHelper implements IVerticalJustificationLine
+{
+	private var _line:TextLine;
+	private var _height:Number;
+
+	public function VJHelper(line:TextLine,h:Number)
+	{
+		_line = line;
+		_height = h;
+	}
+	public function get x():Number
+	{ return _line.x; }
+	public function set x(val:Number):void
+	{ _line.x = val; }
+		
+	public function get y():Number
+	{ return _line.y; }
+	public function set y(val:Number):void
+	{ _line.y = val; }
+		
+	public function get ascent():Number
+	{ return _line.ascent; }
+	public function get descent():Number
+	{ return _line.descent; }
+	public function get height():Number
+	{ return _height; }
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/StandardFlowComposer.as b/textLayout_core/src/flashx/textLayout/compose/StandardFlowComposer.as
new file mode 100755
index 0000000..4f68684
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/StandardFlowComposer.as
@@ -0,0 +1,896 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{	
+	import flash.display.Sprite;
+	import flash.system.Capabilities;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.accessibility.TextAccImpl;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.elements.BackgroundManager;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	[Exclude(name="createBackgroundManager",kind="method")]
+	
+	/** 
+	* The StandardFlowComposer class provides a standard composer and container manager. 
+	*
+	* <p>Each call to <code>compose()</code> or <code>updateAllControllers()</code> normalizes the text flow as a first step.  
+	* The normalizing process checks the parts of the TextFlow object that were modified and takes the following steps:
+	* <ol>
+	* <li> Deletes empty FlowLeafElement and SubParagraphGroupElement objects.</li>
+	* <li> Merges sibling spans that have identical attributes.</li>
+	* <li> Adds an empty paragraph if a flow is empty.</li>
+ 	* </ol>
+ 	* </p>
+	*
+	* <p>To use a StandardFlowComposer, assign it to the
+	* <code>flowComposer</code> property of a TextFlow object. Call the <code>updateAllControllers()</code>
+	* method to lay out and display the text in the containers attached to the flow composer.</p>
+	* 
+	* <p><b>Note:</b> For simple, static text flows, you can also use one of the text line factory classes.
+	* These factory classes will typically create lines with less overhead than a flow composer, but do not
+	* support editing, dynamic changes, or user interaction.</p>
+	* 
+	* @see flashx.textLayout.elements.TextFlow#flowComposer
+	* @includeExample examples\StandardFlowComposer_ClassExample.as -noswf
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*/
+	
+	public class StandardFlowComposer extends FlowComposerBase implements IFlowComposer
+	{
+		/** @private */
+		tlf_internal var _rootElement:ContainerFormattedElement;
+		private var _controllerList:Array;
+		private var _composing:Boolean;
+
+		
+		/** 
+		* Creates a StandardFlowComposer object. 
+		*
+		* <p>To use an StandardFlowComposer object, assign it to the
+		* <code>flowComposer</code> property of a TextFlow object. Call the <code>updateAllControllers()</code>
+		* method to lay out and display the text in the containers attached to the flow composer.</p>
+		* 
+		* @includeExample examples\StandardFlowComposer_constructor.as -noswf
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function StandardFlowComposer():void
+		{
+			super();
+			_controllerList = new Array();
+			_composing = false;
+		}
+
+		/** 
+		 * True, if the flow composer is currently performing a composition operation. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get composing():Boolean
+		{ return _composing; }
+		
+		/** 
+		 * Returns the absolute position of the first content element in the specified ContainerController object.
+		 *
+		 * <p>A position is calculated by counting the division between two characters or other elements of a text flow. 
+		 * The position preceding the first element of a flow is zero. An absolute position is the position
+		 * counting from the beginning of the flow.</p>
+		 * 
+		 * @param controller A ContainerController object associated with this flow composer.
+		 * @return the position before the first character or graphic in the ContainerController.
+		 *
+		 * @includeExample examples\StandardFlowComposer_getAbsoluteStart.as -noswf
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		public function getAbsoluteStart(controller:ContainerController):int
+		{
+			// don't look at controller's relativeStart property - it uses this method.  hmmmm 
+			// TODO: that does seem odd - clean the above implementation up.
+			var stopIdx:int = getControllerIndex(controller);
+			CONFIG::debug { assert(stopIdx != -1,"bad controller to LayoutFlowComposer.getRelativeStart"); }
+			var rslt:int = _rootElement.getAbsoluteStart();
+			for (var idx:int = 0; idx < stopIdx; idx++)
+				rslt += _controllerList[idx].textLength;
+				
+			return rslt;
+		}
+		
+		/** @copy IFlowComposer#rootElement
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		
+		public function get rootElement():ContainerFormattedElement
+		{ return _rootElement; }
+		
+		
+		/** @copy IFlowComposer#setRootElement()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function setRootElement(newRootElement:ContainerFormattedElement):void
+		{
+
+			if (_rootElement != newRootElement)
+			{
+				if (newRootElement is TextFlow && TextFlow(newRootElement).flowComposer != this)
+					TextFlow(newRootElement).flowComposer = this;
+				else
+				{
+					clearCompositionResults();
+
+					detachAllContainers();
+					_rootElement = newRootElement;
+					_textFlow = _rootElement ? _rootElement.getTextFlow() :  null;
+					attachAllContainers();
+				}
+			}
+		}
+		
+		/** @private */
+		tlf_internal function detachAllContainers():void
+		{
+			
+			// detatch accessibility from the containers
+			// Why only the first container?
+			if (_controllerList.length > 0 && _textFlow)
+			{
+				var firstContainerController:ContainerController = getControllerAt(0);
+				var firstContainer:Sprite = firstContainerController.container;
+				if (firstContainer)
+					clearContainerAccessibilityImplementation(firstContainer);
+		  	}
+		  	
+		  	var cont:ContainerController;
+			for each (cont in _controllerList)
+			{
+				cont.clearSelectionShapes();
+				cont.setRootElement(null);
+			}
+		}
+		
+		static private function clearContainerAccessibilityImplementation(cont:Sprite):void
+		{
+			if (cont.accessibilityImplementation)
+			{
+				if (cont.accessibilityImplementation is TextAccImpl)
+					TextAccImpl(cont.accessibilityImplementation).detachListeners();
+				cont.accessibilityImplementation = null;
+			}
+		}
+		
+		/** @private */
+		tlf_internal function attachAllContainers():void
+		{
+			var cont:ContainerController;
+			for each (cont in _controllerList)
+				ContainerController(cont).setRootElement(_rootElement);
+			
+
+			if (_controllerList.length > 0 && _textFlow)
+			{
+				// attach accessibility to the containers
+				// Why only the first container?  There are workflows that this will fail
+				// for example: a pagination workflow that has a composed chain of containers but only displays one at a time.
+				if (textFlow.configuration.enableAccessibility && flash.system.Capabilities.hasAccessibility)
+				{
+					var firstContainer:Sprite = getControllerAt(0).container;
+					if (firstContainer)
+					{
+						clearContainerAccessibilityImplementation(firstContainer);
+						firstContainer.accessibilityImplementation = new TextAccImpl(firstContainer, _textFlow);
+					}
+				}
+				
+				var curContainer:Sprite;
+				// turn off focusRect on all containers
+				for (var i:int = 0; i < _controllerList.length; ++i)
+				{
+					curContainer = getControllerAt(i).container;
+					if (curContainer)
+						curContainer.focusRect = false;
+				} 
+		  	}
+
+			// TODO: can be more efficient? - just damage all
+			clearCompositionResults();				
+		}
+		
+		/** @copy IFlowComposer#numControllers
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get numControllers():int
+		{ return _controllerList ? _controllerList.length : 0; }
+		
+		/** @copy IFlowComposer#addController()
+		 *
+		 * @includeExample examples\StandardFlowComposer_addController.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function addController(controller:ContainerController):void
+		{
+			CONFIG::debug { assert (_controllerList.indexOf(controller) < 0, "adding controller twice"); }
+			_controllerList.push(ContainerController(controller));
+			if (this.numControllers == 1)
+			{				
+				attachAllContainers();
+			}
+			else
+			{
+				controller.setRootElement(_rootElement)
+				var curContainer:Sprite = controller.container;
+				if (curContainer)
+					curContainer.focusRect = false;
+				if (textFlow)
+				{
+					// mark the previous container as geometry damaged - this is more than is needed
+					controller = this.getControllerAt(this.numControllers-2);
+					var damageStart:int = controller.absoluteStart;
+					var damageLen:int = controller.textLength;
+					// watch out for an empty previous container
+					if (damageLen == 0)
+					{
+						if (damageStart != textFlow.textLength)
+							damageLen++;
+						else if (damageStart != 0)
+						{
+							damageStart--;
+							damageLen++;
+						}
+					}
+					if (damageLen)
+						textFlow.damage(damageStart,damageLen,FlowDamageType.GEOMETRY,false);
+				}
+			}
+		}
+		/** @copy IFlowComposer#addControllerAt()
+		 *
+		 * @includeExample examples\StandardFlowComposer_addControllerAt.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function addControllerAt(controller:ContainerController, index:int):void
+		{
+			CONFIG::debug { assert (_controllerList.indexOf(controller) == -1, "adding controller twice"); }
+			detachAllContainers();
+			_controllerList.splice(index,0,ContainerController(controller));
+			attachAllContainers();
+		}
+		
+		/** Removes a trailing controller with no content without doing any damage */
+		private function fastRemoveController(index:int):Boolean
+		{
+			if (index == -1)
+				return true;
+			var cont:ContainerController = _controllerList[index];
+			if (!cont)
+				return true;
+			if (!_textFlow || cont.absoluteStart == _textFlow.textLength)
+			{
+				if (index == 0)
+				{
+					var firstContainer:Sprite = cont.container;
+					if (firstContainer)
+						clearContainerAccessibilityImplementation(firstContainer);				
+				}
+				cont.setRootElement(null);
+				_controllerList.splice(index,1);
+				return true;
+			} 	
+			return false;
+		}
+		
+		/** @copy IFlowComposer#removeController()
+		 *
+		 * @includeExample examples\StandardFlowController_removeController.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function removeController(controller:ContainerController):void
+		{ 
+			var index:int = getControllerIndex(controller);
+			if (!fastRemoveController(index))
+			{
+				detachAllContainers();
+				_controllerList.splice(index,1);
+				attachAllContainers();
+			}
+		}
+		/** @copy IFlowComposer#removeControllerAt()
+		 *
+		 * @includeExample examples\StandardFlowController_removeControllerAt.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		public function removeControllerAt(index:int):void
+		{ 
+			if (!fastRemoveController(index))
+			{
+				detachAllContainers();
+				_controllerList.splice(index,1);
+				attachAllContainers();
+			}
+		}
+		/** @copy IFlowComposer#removeAllControllers()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function removeAllControllers():void
+		{
+			detachAllContainers();
+			_controllerList.splice(0,_controllerList.length);
+		}
+		
+		/** @copy IFlowComposer#getControllerAt()  
+		 * 
+		 * @includeExample examples\StandardFlowComposer_getControllerAt.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		
+		public function getControllerAt(index:int):ContainerController
+		{
+			return _controllerList[index];
+		}
+		
+		/** @copy IFlowComposer#getControllerIndex()  
+		 *
+		 * @includeExample examples\StandardFlowComposer_getControllerIndex.as -noswf
+		 * @playerversion Flash 10
+		 * @player version AIR 1.5
+	 	 * @langversion 3.0
+	 	 * @playerversion AIR 1.5
+	 	 */
+	 	 
+		public function getControllerIndex(controller:ContainerController):int
+		{
+			// TODO: binary search? 
+			for (var idx:int = 0; idx < _controllerList.length; idx++)
+			{
+				if (_controllerList[idx] == controller)
+					return idx;
+			}
+			return -1; 
+		}
+		
+		/** 
+		 * Returns the index of the controller containing the content at the specified position. 
+		 * 
+		 * <p>A position can be considered to be the division between two characters or other elements of a text flow. If 
+		 * the value in <code>absolutePosition</code> is a position between the last character of one 
+		 * container and the first character of the next, then the preceding container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>true</code> and the later container is returned if
+		 * the <code>preferPrevious</code> parameter is set to <code>false</code>.</p>
+		 *
+		 * <p>The method returns -1 if the content at the specified position is not in any container or is outside
+		 * the range of positions in the text flow.</p>
+		 * 
+		 * @param absolutePosition The position of the content for which the container index is sought.
+		 * @param preferPrevious Specifies which container index to return when the position is between the last element in 
+		 * one container and the first element in the next.
+		 * 
+		 * @return 	the index of the container controller or -1 if not found.
+		 *
+		 * @includeExample examples\StandardFlowComposer_findControllerIndexAtPosition.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		
+		public function findControllerIndexAtPosition(absolutePosition:int,preferPrevious:Boolean=false):int
+		{
+			
+			var lo:int = 0;
+			var hi:int = _controllerList.length-1;
+			while (lo <= hi)
+			{
+				var mid:int = (lo+hi)/2;
+				var cont:ContainerController = _controllerList[mid];
+				if (cont.absoluteStart <= absolutePosition)
+				{
+					if (preferPrevious)
+					{
+						if (cont.absoluteStart + cont.textLength >= absolutePosition)
+						{
+							// find first container or first one with non-zero textLength
+							while (mid != 0 && cont.absoluteStart == absolutePosition)
+							{
+								mid--;
+								cont = _controllerList[mid];
+							}
+							return mid;
+						}
+					}
+					else
+					{
+
+						if (cont.absoluteStart == absolutePosition && cont.textLength != 0)
+						{
+							while (mid != 0)
+							{
+								cont = _controllerList[mid-1];
+								if (cont.textLength != 0)
+									break;
+								mid--;
+							}
+							return mid;
+						}
+						if (cont.absoluteStart + cont.textLength > absolutePosition)
+							return mid;
+					}
+					lo = mid+1;
+				}
+				else
+					hi = mid-1;
+			}
+			return -1;
+		}
+
+		/** Clear whatever computed values are left from the last composition, in the flow composer and
+		 * in each of its controllers. @private
+		 */
+		 
+		tlf_internal function clearCompositionResults():void
+		{
+			initializeLines();
+			for each (var cont:ContainerController in _controllerList)
+				cont.clearCompositionResults();
+		}
+
+		/** 
+		 * Composes the content of the root element and updates the display.  
+		 *
+		 * <p>Text layout is conducted in two phases: composition and display. In the composition phase,
+		 * the flow composer calculates how many lines are necessary to display the content as well as the position of these 
+		 * lines in the flow's display containers. In the display phase, 
+		 * the flow composer updates the display object children of its containers. The <code>updateAllControllers()</code>
+		 * method initiates both phases in sequence. The StandardFlowComposer keeps track of changes to content
+		 * so that a full cycle of composition and display is only performed when necessary.</p>
+		 * 
+		 * <p>This method updates all the text lines and the display list immediately and synchronously.</p>
+		 *
+		 * <p>If the contents of any container is changed, the method returns <code>true</code>.</p>
+		 * 
+		 * @return true if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+		 */
+		 
+		public function updateAllControllers():Boolean
+		{
+			return updateToController();
+		}
+		
+		/** 
+		 * Composes and updates the display up to and including the container at the specified index.
+		 * 
+		 * <p>The <code>updateToController()</code> method composes the content and 
+		 * updates the display of all containers up to and including the container at the specified index.
+		 * For example, if you have a chain of 20 containers and specify an index of 10, 
+		 * <code>updateToController()</code> ensures that the first through the tenth (indexes 0-9) 
+		 * containers are composed and displayed. Composition stops at that point. If <code>controllerIndex</code> 
+		 * is -1 (or not specified), then all containers are updated.</p>
+		 *
+		 * <p>This method updates all the text lines and the display list immediately and synchronously.</p>
+		 * 
+		 * <p>If the contents of any container is changed, the method returns <code>true</code>.</p>
+		 * 
+		 * @param controllerIndex index of the last container to update (by default updates all containers)
+		 * @return <code>true</code>, if anything changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		public function updateToController(index:int = int.MAX_VALUE):Boolean
+		{
+			//CONFIG::debug { assert(!_composing,"updateToController: compose in process"); }
+			if (_composing)
+				return false;
+				
+			//note that this will always update the display AND update the
+			//selection.  So, even if nothing has changed that would cause
+			//a recompose, the selection would still be redrawn.
+			var sm:ISelectionManager = textFlow.interactionManager;
+			if (sm)
+				sm.flushPendingOperations();
+			var startController:ContainerController = _composing ? null : internalCompose(-1, index);	
+			var shapesDamaged:Boolean = areShapesDamaged();
+			if (shapesDamaged)
+				updateCompositionShapes();
+
+			if (sm)
+				sm.refreshSelection();
+			releaseLines(startController);
+			return shapesDamaged;
+		}
+		
+		/** 
+		 * Sets the focus to the container that contains the location specified by the <code>absolutePosition</code>
+		 * parameter. 
+		 *
+		 * <p>The StandardFlowComposer calls the <code>setFocus()</code> method of the ContainerController object
+		 * containing the specified text flow position.</p>
+		 * 
+		 * @param absolutePosition Specifies the position in the text flow of the container to receive focus.
+		 * @param preferPrevious If true and the position is before the first character in a container, sets focus to the end of 
+		 *  the previous container.
+		 * 
+		 * @see flash.display.Stage#focus
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function setFocus(absolutePosition:int,leanLeft:Boolean=false):void
+		{
+			var idx:int = findControllerIndexAtPosition(absolutePosition,leanLeft);
+			if (idx == -1)
+				idx = this.numControllers-1;
+			if (idx != -1)
+				_controllerList[idx].setFocus();
+		}
+		
+		/**
+		 * Called by the TextFlow when the interaction manager changes. 
+		 * 
+		 * <p>This function is called automatically. Your code does not typically need to call this
+		 * method. Classes that extend StandardFlowComposer can override this method to update
+		 * event listeners and other properties that depend on the interaction manager.</p>
+		 * 
+		 * @param newInteractionManager The new ISelectionManager instance.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public	function interactionManagerChanged(newInteractionManager:ISelectionManager):void
+		{
+			for each (var controller:ContainerController in _controllerList)
+				controller.interactionManagerChanged(newInteractionManager);
+		}
+
+		
+		private function updateCompositionShapes():void
+		{
+			for each (var controller:ContainerController in _controllerList)
+				controller.updateCompositionShapes(); 
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Composition
+		//
+		//--------------------------------------------------------------------------
+		
+		/** @private Override required because we may be damaged if the last container has scrolling */
+		public override function isDamaged(absolutePosition:int):Boolean
+		{
+			// Returns true if any text from _damageAbsoluteStart through absolutePosition needs to be recomposed
+			if (!super.isDamaged(absolutePosition))
+			{	
+				if (absolutePosition == _textFlow.textLength)
+				{
+					var container:ContainerController = getControllerAt(numControllers-1);
+					if (container && (container.verticalScrollPolicy != ScrollPolicy.OFF || container.horizontalScrollPolicy != ScrollPolicy.OFF))
+						return true;
+				}
+				return false;
+			}
+				
+			return true;
+		}
+
+		/** Returns true if composition is necessary, false otherwise */
+		protected function preCompose():Boolean
+		{
+			CONFIG::debug { checkFirstDamaged(); }
+			rootElement.preCompose();
+			
+			// No content, nothing to compose - TextFlow isn't loaded  or connected
+			CONFIG::debug { assert(rootElement.textLength != 0,"bad TextFlow after normalize"); }
+			
+			// brand new content
+			if (numLines == 0)
+				initializeLines();
+				
+			return isDamaged(rootElement.getAbsoluteStart() + rootElement.textLength);
+		}
+		
+		/** @private */
+		tlf_internal function getComposeState():ComposeState
+		{ return ComposeState.getComposeState(); }
+		
+		/** @private */
+		tlf_internal function releaseComposeState(state:ComposeState):void
+		{ ComposeState.releaseComposeState(state); }
+		
+		/** @private Return the first damaged controller */
+		tlf_internal function callTheComposer(composeToPosition:int, controllerEndIndex:int):ContainerController
+		{
+			
+			if (_damageAbsoluteStart == rootElement.getAbsoluteStart()+rootElement.textLength)
+				return getControllerAt(numControllers-1);;
+				
+			var state:ComposeState = getComposeState();
+			
+			var lastComposedPosition:int = state.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+			if (_damageAbsoluteStart < lastComposedPosition)
+				_damageAbsoluteStart = lastComposedPosition;
+			CONFIG::debug { checkFirstDamaged(); }
+			
+			// make sure there is an empty TextFlowLine covering any trailing content
+			finalizeLinesAfterCompose();
+			var startController:ContainerController = state.startController;
+			
+			releaseComposeState(state);
+							
+			textFlow.dispatchEvent(new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE,false,false,textFlow, 0,lastComposedPosition));
+
+			CONFIG::debug { textFlow.debugCheckTextFlow(); }
+			return startController;
+		}
+		
+		private var lastBPDirectionScrollPosition:Number = Number.NEGATIVE_INFINITY;
+		
+		static private function getBPDirectionScrollPosition(bp:String,cont:ContainerController):Number
+		{
+			return bp == BlockProgression.TB ? cont.verticalScrollPosition : cont.horizontalScrollPosition;
+		}
+		
+		/** Bottleneck function for all types of compose. Does the work of compose, no matter how it is called. @private 
+		 * @return first controller with changed shapes
+		 */
+		private function internalCompose(composeToPosition:int = -1, composeToControllerIndex:int = -1):ContainerController
+		{
+			var sm:ISelectionManager = textFlow.interactionManager;
+			if (sm)
+				sm.flushPendingOperations();
+			
+			if (numControllers == 0)
+				return null;
+
+			if (composeToControllerIndex < 0)
+			{
+				if (composeToPosition >= 0 && damageAbsoluteStart >= composeToPosition)
+					return null;
+			}
+			else
+			{
+				var controller:ContainerController = getControllerAt(Math.min(composeToControllerIndex,numControllers-1));
+				if (damageAbsoluteStart > controller.absoluteStart+controller.textLength)
+					return null;
+			}
+				
+			// trace("internalCompose: damageAbsoluteStart",damageAbsoluteStart);
+			
+			var lastController:ContainerController;
+			var bp:String;
+			if (composeToControllerIndex == numControllers-1)
+			{
+				lastController = this.getControllerAt(numControllers-1);
+				// skip it if damageAbsoluteStart is past the end of the controller.  are there risks here? AND scrollpositions haven't changed since last composeToControllerIndex
+				var a:Array = lastController.findFirstAndLastVisibleLine();
+				var lastVisibleLine:TextFlowLine = a[1];
+				if (lastVisibleLine)
+				{
+					bp = rootElement.computedFormat.blockProgression
+					if (getBPDirectionScrollPosition(bp,lastController) == this.lastBPDirectionScrollPosition && damageAbsoluteStart >= lastVisibleLine.absoluteStart+lastVisibleLine.textLength)
+						return null;
+				}
+			}
+			lastBPDirectionScrollPosition = Number.NEGATIVE_INFINITY;
+			
+			CONFIG::debug { assert(_composing == false,"internalCompose: Recursive call"); }
+				
+			_composing = true;
+			
+			var startController:ContainerController;
+			
+			try
+			{	
+				var cont:ContainerController;	// scratch
+				if (textFlow && numControllers != 0)
+				{
+					if (preCompose())
+					{
+						startController = callTheComposer(composeToPosition, composeToControllerIndex);
+						if (startController)
+						{
+							var idx:int = this.getControllerIndex(startController);
+							while (idx < numControllers)
+								getControllerAt(idx++).shapesInvalid = true;
+						}
+					}
+				}
+			}
+			catch (e:Error)
+			{
+				_composing = false;
+				throw(e);
+			}
+			_composing = false;
+			
+			if (lastController)
+			{
+				lastBPDirectionScrollPosition = getBPDirectionScrollPosition(bp,lastController);
+			}
+			
+			return startController;
+		}
+		
+		
+		/** @private */
+		tlf_internal function areShapesDamaged():Boolean
+		{
+			var cont:ContainerController;	// scratch
+			// TODO: a flag on this?
+			for each (cont in _controllerList)
+			{
+				if (cont.shapesInvalid)
+					return true;
+			}
+			return false;
+		}
+		
+		/** 
+		 * Calculates how many lines are necessary to display the content in the root element of the flow and the positions of these 
+		 * lines in the flow's display containers.
+		 * 
+		 * <p>The <code>compose()</code> method only composes content if it has changed since the last composition operation. 
+		 * Results are saved so that subsequent
+		 * calls to <code>compose()</code> or <code>updateAllControllers()</code> do not perform an additional recomposition
+		 * if the flow content has not changed.</p>
+		 * 
+		 * <p>If the contents of any container have changed, the method returns <code>true</code>.</p>
+		 * 
+		 * @return true if anything changed.
+		 *
+		 * @includeExample examples\StandardFlowComposer_compose.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #updateAllControllers()
+	 	 * @see #updateToController()
+		 */
+		public function compose():Boolean
+		{
+			//CONFIG::debug { assert(!_composing,"compose: compose in process"); }
+			return _composing ? false : internalCompose() != null;
+		}
+		
+		/** @copy IFlowComposer#composeToPosition()
+		 *
+		 * @includeExample examples\StandardFlowComposer_composeToPosition.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function composeToPosition(absolutePosition:int = int.MAX_VALUE):Boolean
+		{
+			//CONFIG::debug { assert(!_composing,"composeToPosition: compose in process"); }
+			return _composing ? false : internalCompose(absolutePosition, -1) != null;
+		}
+		
+		/** @copy IFlowComposer#composeToController()
+		 *
+		 * @includeExample examples\StandardFlowComposer_composeToController.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function composeToController(index:int = int.MAX_VALUE):Boolean
+		{
+			//CONFIG::debug { assert(!_composing,"composeToController: compose in process"); }
+			return _composing ? false : internalCompose(-1, index) != null;
+		}
+		
+		/** Release lines in paragraphs that aren't referenced externally, so that they can be garbage collected
+		 * if necessary. Iterates through the lines, looking for lines that do not have a valid parent. If all the
+		 * lines in a paragraph have no parent, we call the paragraph's TextBlock.releaseLines(). 
+		 */
+		private function releaseLines(startController:ContainerController):void
+		{
+			var currentParagraph:ParagraphElement = null;
+			var inUse:Boolean = false;
+			var lastLine:int = lines.length;
+			for (var lineIndex:int = startController ? findLineIndexAtPosition(startController.absoluteStart) : 0; lineIndex < lastLine; lineIndex++)
+			{
+				var line:TextFlowLine = lines[lineIndex];
+				var paragraph:ParagraphElement = line.paragraph;
+				if (paragraph != currentParagraph)		
+				{
+					// We're on a new paragraph. Release the lines from the old para, if they weren't used,
+					// and set up the new para.
+					if (!inUse && currentParagraph)
+						currentParagraph.releaseTextBlock();
+					currentParagraph = paragraph;
+					inUse = false;
+				}
+				if (!inUse && !line.isDamaged())
+				{
+					var textLine:TextLine = line.getTextLine();
+					if (textLine != null && textLine.parent != null)
+						inUse = true;
+				}
+			}
+			// Release the lines from the last para, if they weren't used.
+			if (!inUse && currentParagraph && currentParagraph.hasBlockElement())
+				currentParagraph.releaseTextBlock();
+		}
+		
+		/** @private */
+		public function createBackgroundManager():BackgroundManager
+		{ return new BackgroundManager(); }
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/TextFlowLine.as b/textLayout_core/src/flashx/textLayout/compose/TextFlowLine.as
new file mode 100755
index 0000000..a3c41aa
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/TextFlowLine.as
@@ -0,0 +1,2169 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.display.DisplayObject;
+	import flash.display.GraphicsPathCommand;
+	import flash.display.GraphicsPathWinding;
+	import flash.display.Shape;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.text.engine.TextRotation;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.edit.SelectionFormat;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.FlowValueHolder;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.external.WeakRef;
+	import flashx.textLayout.formats.BackgroundColor;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.JustificationRule;
+	import flashx.textLayout.formats.LeadingModel;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.formats.TextDecoration;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.CharacterUtil;
+	
+	use namespace tlf_internal;
+	
+	
+	/** 
+	 * The TextFlowLine class represents a single line of text in a text flow.
+	 * 
+	 * <p>Use this class to access information about how a line of text has been composed: its position, 
+	 * height, width, and so on. When the text flow (TextFlow) is modified, the lines immediately before and at the  
+	 * site of the modification are marked as invalid because they need to be recomposed. Lines after
+	 * the site of the modification might not be damaged immediately, but they might be regenerated once the
+	 * text is composed. You can access a TextFlowLine that has been damaged, but any values you access
+	 * reflect the old state of the TextFlow. When the TextFlow is recomposed, it generates new lines and you can 
+	 * get the new line for a given position by calling <code>TextFlow.flowComposer.findLineAtPosition()</code>.</p>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	public final class TextFlowLine implements IVerticalJustificationLine 
+	{
+
+		 
+		
+		/** @private */
+				
+		private var _absoluteStart:int;		// text-offset of start of line - from beginning of the TextFlow
+		private var _textLength:int;	// number of chars to next line (incl trailing spaces, etc.)
+		private var _height:Number = 0;		// y advance
+		private var _spaceBefore:Number = 0;	// amount of vertical space to leave at the top of the line
+		private var _spaceAfter:Number = 0;	// amount of vertical space to leave at the bottom of the line
+		private var _x:Number = 0;			// left edge of line
+		private var _y:Number = 0;			// top edge of line
+		private var _outerTargetWidth:Number = 0; // width line is composed to, excluding indents
+		private var _para:ParagraphElement;			// owning paragraph
+		private var _controller:ContainerController;	// what frame the line was composed into
+		private var _columnIndex:int;			// column number in the container
+		
+		private var _adornCount:int = 0;
+		
+		// added to support TextFlowLine when TextLine not available
+		private var _ascent:Number;
+		private var _descent:Number;
+		private var _targetWidth:Number;
+		private var _validity:String;
+		private var _unjustifiedTextWidth:Number;
+		private var _textWidth:Number;
+		private var _textHeight:Number;
+		private var _lineOffset:Number;
+		private var _released:Boolean;	// True if line has been released from the TextBlock
+		
+		private var _textLineCache:WeakRef;
+		
+		 /**
+		 * The height of the text line, which is equal to <code>ascent</code> plus <code>descent</code>. The 
+		 * value is calculated based on the difference between the baselines that bound the line, either 
+		 * ideographic top and bottom or ascent and descent depending on whether the baseline at y=0 
+		 * is ideographic (for example, TextBaseline.IDEOGRAPHIC_TOP) or not. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.text.engine.TextBaseline TextBaseline
+	 	 */
+		
+		public function get textHeight():Number 
+		{ return _textHeight; }
+		
+		/** @private - the selection block cache */
+		static private var _selectionBlockCache:Dictionary = new Dictionary(true);
+		
+		private static const EMPTY_LINE_WIDTH:Number = 2;		// default size of empty line selection
+
+		/** Constructor - creates a new TextFlowLine instance. 
+		 *  <p><strong>Note</strong>: No client should call this. It's exposed for writing your own composer.</p>
+		 *
+		 * @param textLine The TextLine display object to use for this line.
+		 * @param paragraph The paragraph (ParagraphElement) in which to place the line.
+		 * @param outerTargetWidth The width the line is composed to, excluding indents.
+		 * @param lineOffset The line's offset in pixels from the appropriate container inset (as dictated by paragraph direction and container block progression), prior to alignment of lines in the paragraph. 
+		 * @param absoluteStart	The character position in the text flow at which the line begins.
+		 * @param numChars	The number of characters in the line.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flash.text.engine.TextLine
+	 	 * @see flashx.textLayout.elements.ParagraphElement
+	 	 * @see #absoluteStart
+	 	 */
+	 	 
+		public function TextFlowLine(textLine:TextLine, paragraph:ParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0)
+		{
+			initialize(paragraph, outerTargetWidth, lineOffset, absoluteStart,numChars,textLine);		
+		}
+		
+		/** @private */
+		tlf_internal function initialize(paragraph:ParagraphElement, outerTargetWidth:Number = 0, lineOffset:Number = 0, absoluteStart:int = 0, numChars:int = 0, textLine:TextLine = null):void
+		{
+			_para = paragraph;
+			_outerTargetWidth = outerTargetWidth;
+			_absoluteStart = absoluteStart;
+			_textLength = numChars;
+			_released = (textLine == null);
+			if (textLine)
+			{
+				_textLineCache = new WeakRef(textLine);
+				textLine.userData = this;
+				_targetWidth = textLine.specifiedWidth;
+				_ascent = textLine.ascent;
+				_descent = textLine.descent;
+				_unjustifiedTextWidth = textLine.unjustifiedTextWidth;
+				_textWidth = textLine.textWidth;
+				_textHeight = textLine.textHeight;
+				_lineOffset = lineOffset;
+				_validity = TextLineValidity.VALID;
+			}
+			else 
+				_validity = TextLineValidity.INVALID;
+		}
+		
+		/** @private */
+		tlf_internal function releaseTextLine():void
+		{ _textLineCache = null; }
+
+		/** @private */
+		tlf_internal function peekTextLine():TextLine
+		{ return _textLineCache ? _textLineCache.get() : null; }
+				
+		/** 
+		 * The horizontal position of the line relative to its container, expressed as the offset in pixels from the 
+		 * left of the container.
+		 * <p><strong>Note: </strong>Although this property is technically <code>read-write</code>, 
+		 * you should treat it as <code>read-only</code>. The setter exists only to satisfy the
+		 * requirements of the IVerticalJustificationLine interface that defines both a getter and setter for this property.
+		 * Use of the setter, though possible, will lead to unpredictable results.
+		 * </p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #y
+		 */
+		public function get x():Number
+		{ return _x; }
+		
+		/** 
+		 * This comment is ignored, but the setter should not be used and exists only to satisfy
+		 * the IVerticalJustificationLine interface.
+		 * @see flashx.textLayout.compose.IVerticalJustificationLine 
+		 * @private 
+		 */
+		public function set x(lineX:Number):void
+		{ _x = lineX; }
+		
+		/** 
+		 * The vertical position of the line relative to its container, expressed as the offset in pixels from the top 
+		 * of the container.
+		 * <p><strong>Note: </strong>Although this property is technically <code>read-write</code>, 
+		 * you should treat it as <code>read-only</code>. The setter exists only to satisfy the
+		 * requirements of the IVerticalJustificationLine interface that defines both a getter and setter for this property.
+		 * Use of the setter, though possible, will lead to unpredictable results.
+		 * </p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see #x
+		 */
+		public function get y():Number
+		{ return _y; }
+		
+		/** This comment is ignored, but the setter should not be used and exists only to satisfy
+		 * the IVerticalJustificationLine interface.
+		 * @see flashx.textLayout.compose.IVerticalJustificationLine
+		 * @private
+		 */
+		public function set y(lineY:Number):void
+		{ _y = lineY; }
+		
+		/** @private */
+		tlf_internal function setXYAndHeight(lineX:Number,lineY:Number,lineHeight:Number):void
+		{
+			_x = lineX;
+			_y = lineY;
+			_height = lineHeight
+		}
+		
+		/** 
+		 * One of the values from TextFlowLineLocation for specifying a line's location within a paragraph.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.elements.ParagraphElement
+	 	 * @see TextFlowLineLocation
+		 */
+		 
+		public function get location():int
+		{
+			if (_para)
+			{
+				var lineStart:int = _absoluteStart - _para.getAbsoluteStart();
+				
+				// Initialize settings for location
+				if (lineStart == 0)		// we're at the start of the paragraph
+					return _textLength == _para.textLength ? TextFlowLineLocation.ONLY : TextFlowLineLocation.FIRST;
+				if (lineStart + _textLength == _para.textLength)	// we're at the end of the para
+					return TextFlowLineLocation.LAST;
+			}
+			return TextFlowLineLocation.MIDDLE;
+		}
+		
+		/** 
+		 * The controller (ContainerController object) for the container in which the line has been placed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.container.ContainerController 
+		 */
+		 
+		public function get controller():ContainerController
+		{ return _controller; }
+		
+		/** The number of the column in which the line has been placed, with the first column being 0.
+		 *		
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get columnIndex():int
+		{ return _columnIndex; }
+		
+		/** @private */
+		tlf_internal function setController(cont:ContainerController,colNumber:int):void
+		{ 
+			_controller = cont as ContainerController;
+			_columnIndex = colNumber;
+		}
+		
+		/** The height of the line in pixels.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		public function get height():Number
+		{ return _height; }
+		
+		/** 
+		 * @copy flash.text.engine.TextLine#ascent
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function get ascent():Number
+		{ return _ascent; }
+		
+		/** 
+		 * @copy flash.text.engine.TextLine#descent
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function get descent():Number
+		{ return _descent; }
+		
+		/** 
+		 * The line's offset in pixels from the appropriate container inset (as dictated by paragraph direction and container block progression), 
+		 * prior to alignment of lines in the paragraph.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineOffset():Number
+		{
+			return _lineOffset;
+		}
+		
+				
+		/** 
+		 * The paragraph (ParagraphElement) in which the line resides.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.elements.ParagraphElement
+	 	 */
+	 	 
+		public function get paragraph():ParagraphElement
+		{ return _para; }
+		
+		/** 
+		 * The location of the line as an absolute character position in the TextFlow object.
+		 * 
+		 * @return 	the character position in the text flow at which the line begins.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 *
+ 		 * @see flashx.textLayout.elements.TextFlow
+		 */
+		 
+		public function get absoluteStart():int
+		{ return _absoluteStart; }
+		/** @private */
+		tlf_internal function setAbsoluteStart(val:int):void
+		{ _absoluteStart = val; }
+				
+		/** 
+		 * The number of characters to the next line, including trailing spaces. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	
+		public function get textLength():int
+		{ return _textLength; }
+		/** @private */
+		tlf_internal function setTextLength(val:int):void
+		{ 
+			_textLength = val; 
+		//	assert(_validity == TextLineValidity.INVALID, "not already damaged");
+			damage(TextLineValidity.INVALID);
+		}
+		
+		/** 
+		 * The amount of space to leave before the line.
+		 * <p>If the line is the first line of a paragraph that has a space-before applied, the line will have
+		 * a <code>spaceBefore</code> value. If the line comes at the top of a column, <code>spaceBefore</code> is ignored. 
+		 * Otherwise, the line follows another line in the column, and it is positioned vertically to insure that there is
+		 * at least this much space left between this line and the last line of the preceding paragraph.</p> 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.formats.TextLayoutFormat#paragraphSpaceBefore TextLayoutFormat.paragraphSpaceBefore
+		 */
+		 
+		public function get spaceBefore():Number
+		{ return _spaceBefore; }
+		/** @private */
+		tlf_internal function setSpaceBefore(val:Number):void
+		{ _spaceBefore = val; }
+		
+		/** 
+		 * The amount of space to leave after the line.
+		 * <p>If the line is the last line of a paragraph that has a space-after, the line will have
+		 * a <code>spaceAfter</code> value. If the line comes at the bottom of a column, then the <code>spaceAfter</code>
+		 * is ignored. Otherwise, the line comes before another line in the column, and the following line must be positioned vertically to
+		 * insure that there is at least this much space left between this last line of the paragraph and the first
+		 * line of the following paragraph.</p> 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flashx.textLayout.formats.TextLayoutFormat#paragraphSpaceAfter TextLayoutFormat.paragraphSpaceAfter
+		 */
+		 
+		public function get spaceAfter():Number
+		{ return _spaceAfter; }
+		/** @private */
+		tlf_internal function setSpaceAfter(val:Number):void
+		{ _spaceAfter = val; }
+		
+		/** @private 
+		 * Target width not including paragraph indents @private */
+		 
+		tlf_internal function get outerTargetWidth():Number
+		{ return _outerTargetWidth; }
+		
+		/** @private */
+		tlf_internal function set outerTargetWidth(val:Number):void
+		{ _outerTargetWidth = val; }
+		
+		/** @private  
+		 * Amount of space used to break the line
+		 * <p>The target width is the amount of space allowed for the line, including the space required for indents.</p>
+		 */
+		tlf_internal function get targetWidth():Number
+		{ return _targetWidth; }
+										
+		/** 
+		 * Returns the bounds of the line as a rectangle.
+		 *
+		 * @return a rectangle that represents the boundaries of the line.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function getBounds():Rectangle
+		{	
+			var textLine:TextLine = getTextLine(true);
+			if (!textLine)
+				return new Rectangle();
+
+			// TODO: just use the textLine.x and textLine.y - after all getTextLine now sets them.
+			// not going to change this right now though
+			var bp:String = paragraph.getAncestorWithContainer().computedFormat.blockProgression;
+			var shapeX:Number = createShapeX();
+			var shapeY:Number = createShapeY(bp);
+			if (bp == BlockProgression.TB)
+				shapeY += descent-textLine.height;
+			return new Rectangle(shapeX, shapeY, textLine.width, textLine.height);			
+		}
+								
+		/** The validity of the line. 
+		 * <p>A line can be invalid if the text, the attributes applied to it, or the controller settings have
+		 * changed since the line was created. An invalid line can still be displayed, and you can use it, but the values
+		 * used will be the values at the time it was created. The line returned by <code>getTextLine()</code> also will be in an
+		 * invalid state. </p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #getTextLine()
+	 	 * @see flash.text.engine.TextLine#validity TextLine.validity
+	 	 * @see FlowDamageType#GEOMETRY
+		 */
+		 
+		public function get validity():String
+		{ 
+			// A TextLine may be invalidated separately from the TextFlowLine, when the invalidation is driven from the Player (e.g. changes have been made directly). 
+			// If the TextFlowLine is marked valid, the line may still be invalid if the TextLine has been marked invalid.
+			// If the line has been released (TextBlock.releaseLines called), then it may have an existing TextLine that got marked invalid by the Player 
+			// when it was released. We want to ignore that invalid marking.
+			if (!_released)
+			{
+				var textLine:TextLine = peekTextLine();
+				if (textLine && (_validity == FlowDamageType.GEOMETRY || _validity == TextLineValidity.VALID) && textLine.validity != TextLineValidity.VALID)
+					_validity = textLine.validity;
+			}
+			return _validity; 
+		}
+		
+		/** 
+		 * The width of the line if it was not justified. For unjustified text, this value is the same as <code>textLength</code>. 
+		 * For justified text, this value is what the length would have been without justification, and <code>textLength</code> 
+		 * represents the actual line width. For example, when the following String is justified and assigned a width of 500, it 
+		 * has an actual width of 500 but an unjustified width of 268.9921875. 
+		 *
+		 * @internal TBD: add graphic of justified line
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function get unjustifiedTextWidth():Number
+		{ 
+			// hack - outerTargetWidth holds value from the factory
+			return _unjustifiedTextWidth + (_outerTargetWidth - targetWidth); 
+		}
+		
+		/** @private 
+		 * True if the line needs composing. */
+		tlf_internal function isDamaged():Boolean
+		{ 
+			if (_validity != TextLineValidity.VALID)
+				return true;
+			if (!_released)
+			{
+				var textLine:TextLine = peekTextLine(); 
+				if (textLine && textLine.validity != TextLineValidity.VALID)
+					return true;
+			}
+			return false;
+		}
+		
+		/** @private
+		 * Mark the line as valid */
+		tlf_internal function clearDamage():void
+		{ 
+			CONFIG::debug { assert(_validity == FlowDamageType.GEOMETRY, "can't clear damage other than geometry"); }
+			if (_validity == TextLineValidity.VALID)		// already is valid
+				return;	
+			_validity = TextLineValidity.VALID; 
+			
+			//CONFIG::debug { assert(_textLineCache != null, "bad call to clearDamage"); }
+
+			var textLine:TextLine =  peekTextLine();
+
+			// The line in the cache, if there is one, is either invalid because its been released, or its geometry_damaged, or its already valid.
+			CONFIG::debug { assert(!textLine || _released || textLine.validity == TextLineValidity.VALID || textLine.validity == FlowDamageType.GEOMETRY, "can't clear TextLine damage other than geometry"); }
+
+			if (textLine && !_released)	// mark the TextLine as well
+			{
+				textLine.validity = TextLineValidity.VALID;
+				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",TextLineValidity.VALID);  }
+			}
+		}
+		
+		/** @private
+		 * Mark the line as damaged */
+		 
+		tlf_internal function damage(damageType:String):void
+		{
+			// trace("TextFlowLine.damage ", this.start.toString(), this.textLength.toString());
+			if (_validity == damageType || _validity == TextLineValidity.INVALID)
+				return;	// totally damaged
+			_validity = damageType;
+			
+			var textLine:TextLine = peekTextLine();
+			if (textLine && textLine.validity != TextLineValidity.INVALID)
+			{
+				textLine.validity = _validity;
+				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",damageType);  }
+			}
+		}
+		
+		/** @private */
+		CONFIG::debug public function toString():String
+		{
+			return "x:" + x + " y: " + y + " absoluteStart:" + absoluteStart + " textLength:" + textLength +  " location: " + location + " validity: " + _validity;
+		}
+	
+		/** 
+		 * Indicates whether the <code>flash.text.engine.TextLine</code> object for this TextFlowLine exists.  
+		 * The value is <code>true</code> if the TextLine object has <em>not</em> been garbage collected and 
+		 * <code>false</code> if it has been.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+	 	 * @see flash.text.engine.TextLine TextLine
+		 */
+		 
+		public function get textLineExists():Boolean
+		{
+			return peekTextLine() != null;			
+		}
+
+		/** 
+		 * Returns the <code>flash.text.engine.TextLine</code> object for this line, which might be recreated 
+		 * if it does not exist due to garbage collection. Set <code>forceValid</code> to <code>true</code>
+		 * to cause the TextLine to be regenerated. Returns null if the TextLine cannot be recreated.
+		 *.
+		 * @param forceValid	if true, the TextLine is regenerated, if it exists but is invalid.
+		 *
+		 * @return object for this line or <code>null</code> if the TextLine object cannot be 
+		 * recreated.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flash.text.engine.TextLine TextLine
+		 */
+		 
+		public function getTextLine(forceValid:Boolean = false):TextLine
+		{ 				
+			var textLine:TextLine = peekTextLine();
+			if (!textLine || (textLine.validity != TextLineValidity.VALID && forceValid))
+			{
+				if (isDamaged() && validity != FlowDamageType.GEOMETRY)
+					return null;
+				
+				var textBlock:TextBlock = paragraph.getTextBlock();
+
+				// regenerate the whole paragraph at once, up to current position. The TextBlock may already contain valid
+				// lines that got generated on a prior call to getTextLine but couldn't be added to the cache (e.g., because
+				// the cache contains an invalid line that is in the display list), so we check for that before making a new line.
+				var previousLine:TextLine;
+				var currentLine:TextLine = textBlock.firstLine;
+				var flowComposer:IFlowComposer = paragraph.getTextFlow().flowComposer;
+				var lineIndex:int = flowComposer.findLineIndexAtPosition(paragraph.getAbsoluteStart());
+				do
+				{
+					var line:TextFlowLine = flowComposer.getLineAt(lineIndex);
+					CONFIG::debug { assert (line.paragraph == paragraph, "Expecting line in same paragraph"); }
+					if (currentLine != null && currentLine.validity == TextLineValidity.VALID)
+					{
+						textLine = currentLine;
+						currentLine = currentLine.nextLine;
+						
+						line.updateTextLineCache(textLine);
+					}
+					else
+					{
+						textLine = line.recreateTextLine(textBlock, previousLine);
+						currentLine = null;
+					}
+					previousLine = textLine;
+					++lineIndex;
+				} while (line != this);			
+			}
+			
+			if(textLine != null && textLine.numChildren == 0 && _adornCount > 0)
+			{
+				var para:ParagraphElement = this.paragraph;
+				var paraStart:int = para.getAbsoluteStart();
+				var elem:FlowLeafElement = para.findLeaf(this.absoluteStart - paraStart);
+				var elemStart:int = elem.getAbsoluteStart();
+				
+				createAdornments(para.getAncestorWithContainer().computedFormat.blockProgression,elem, elemStart);		
+			}
+			
+			return textLine;
+		}
+		
+		/** @private Regenerate the TextLine -- called when textLine has been gc'ed */
+		tlf_internal function recreateTextLine(textBlock:TextBlock, previousLine:TextLine):TextLine
+		{
+			var textLine:TextLine;
+			
+			// If we already have a valid text line, just return it.
+			if (!_released)
+			{
+				textLine = peekTextLine();
+				if (textLine)
+					return textLine;
+			}
+			
+			var textFlow:TextFlow = paragraph.getTextFlow();
+			var flowComposer:IFlowComposer = textFlow.flowComposer;
+			var swfContext:ISWFContext = flowComposer.swfContext ? flowComposer.swfContext : BaseCompose.globalSWFContext;
+			
+			textLine = TextLineRecycler.getLineForReuse();
+			if (textLine)
+			{
+				CONFIG::debug { assert(textFlow.backgroundManager == null || textFlow.backgroundManager.lineDict[textLine] === undefined,"Bad TextLine in recycler cache"); }
+				textLine = swfContext.callInContext(textBlock["recreateTextLine"], textBlock, [ textLine, previousLine, _targetWidth, _lineOffset, true ]);
+			}
+			else
+				textLine = swfContext.callInContext(textBlock.createTextLine, textBlock, [ previousLine, _targetWidth, _lineOffset, true ]);
+			
+			textLine.x = createShapeX();
+			CONFIG::debug { Debugging.traceFTEAssign(textLine,"x", createShapeX());  }
+			textLine.y = createShapeY(textFlow.computedFormat.blockProgression);
+			CONFIG::debug { Debugging.traceFTEAssign(textLine,"y", createShapeY(textFlow.computedFormat.blockProgression));  }
+			textLine.doubleClickEnabled = true;
+
+			updateTextLineCache(textLine);
+			
+			return textLine;
+		}
+		
+		/** the rule is that all "displayed" lines must be in the TextFlowLine textLineCache.  Put this new line in the cache iff there isn't already a displayed line */
+		private function updateTextLineCache(textLine:TextLine):void
+		{
+			textLine.userData = this;	
+			var existingTextLine:TextLine = peekTextLine();
+			// If there is an existing, released line, and it is currently being displayed, we can't replace it in the cache.
+			if (!existingTextLine || existingTextLine.parent == null)
+			{
+				if (existingTextLine != textLine)
+					_textLineCache = new WeakRef(textLine);	
+				_released = false;		
+			}
+		}
+		
+		/** @private */
+		tlf_internal function markReleased():void
+		{
+			_released = true;
+		}
+		
+		/** @private */
+		tlf_internal function createShape(bp:String):TextLine
+		{
+			var textLine:TextLine = getTextLine();
+			
+			var newX:Number = createShapeX();
+			//if (int(newX*20) != int(textLine.x*20))
+			{
+				textLine.x = newX;
+				CONFIG::debug { Debugging.traceFTEAssign(textLine,"x", newX);  }
+			}
+			var newY:Number = createShapeY(bp);
+			//if (int(newY*20) != int(textLine.y*20))
+			{
+				textLine.y = newY;
+				CONFIG::debug { Debugging.traceFTEAssign(textLine,"y", newY);  }
+			}
+			return textLine;
+		}
+		
+		private function createShapeX():Number
+		{ return x; }
+		
+		private function createShapeY(bp:String):Number
+		{ return bp == BlockProgression.RL ? y : y + _ascent; }
+        
+         /** @private 
+         * Scan through the format runs within the line, and draw any underline or strikethrough that might need it
+		 */
+		 
+		tlf_internal function createAdornments(blockProgression:String,elem:FlowLeafElement,elemStart:int):void
+		{
+			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to createAdornments"); } 
+			var endPos:int = _absoluteStart + _textLength;
+			
+			//init adornments back to 0
+			_adornCount = 0;
+
+			for (;;)
+			{
+				var format:ITextLayoutFormat = elem.computedFormat;
+
+				_adornCount += elem.updateAdornments(this, blockProgression);
+				
+				var fvh:FlowValueHolder = elem.format as FlowValueHolder;
+				if(fvh && fvh.userStyles && fvh.userStyles.imeStatus)
+				{
+					elem.updateIMEAdornments(this, blockProgression, fvh.userStyles.imeStatus as String);
+				}
+				elemStart += elem.textLength;
+				if (elemStart >= endPos)
+					break;
+				elem = elem.getNextLeaf(_para);
+				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
+			}
+		}
+        
+       /** @private 
+         * Scan through the format runs within the line, and figure out what the leading for the overall line is.
+		 * The line's leading is equal to the maximum leading of any individual run within the line.
+		 * The leading in an individual format run is calculated by looking at the leading attribute in the
+		 * CharacterFormat. If it is set to a value, we just use that value. Otherwise, if it is set to AUTO,
+		 * we calculate the leading based on the point size and the auto leading percentage from the ParagraphFormat.
+		 */
+		 
+		tlf_internal function getLineLeading(bp:String,elem:FlowLeafElement,elemStart:int):Number
+		{
+			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getLineLeading"); } 
+			var endPos:int = _absoluteStart + _textLength;
+			var totalLeading:Number = 0;
+			CONFIG::debug { assert(elem.getAncestorWithContainer() != null,"element with no container"); }
+			for (;;)
+			{
+				//this is kinda bunk and really shouldn't be here, but I'm loath to find a better way....
+				//ignore the leading on a TCY Block.
+				//if the elem is in a TCYBlock, AND it is not the only block in the line, "skip" it
+				if (!(bp == BlockProgression.RL && (elem.parent is TCYElement) &&  (!isNaN(totalLeading) || (elem.textLength != this.textLength))))
+				{
+					var elemLeading:Number = TextLayoutFormat.lineHeightProperty.computeActualPropertyValue(elem.computedFormat.lineHeight,elem.getEffectiveFontSize());
+					totalLeading = Math.max(totalLeading, elemLeading);
+				}
+				elemStart += elem.textLength;
+				if (elemStart >= endPos)
+					break;
+				elem = elem.getNextLeaf(_para);
+				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
+			}
+			return totalLeading;
+		}
+        
+		/** @private 
+		 * Scan through the format runs within the line, and figure out what the typographic ascent (i.e. ascent relative to the 
+		 * Roman baseline) for the overall line is. Normally it is the distance between the Roman and Ascent baselines, 
+		 * but it may be adjusted upwards by the width/height of the GraphicElement.
+		 */
+		tlf_internal function getLineTypographicAscent(elem:FlowLeafElement,elemStart:int):Number
+		{
+			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getLineTypographicAscent"); } 
+			return getTextLineTypographicAscent(getTextLine(), elem, elemStart, absoluteStart+textLength, _para);
+		}
+        
+		/** @private 
+		 * Scan through the format runs within the line, and figure out what the typographic ascent (i.e. ascent relative to the 
+		 * Roman baseline) for the overall line is. Normally it is the distance between the Roman and Ascent baselines, 
+		 * but it may be adjusted upwards by the width/height of the GraphicElement.
+		 */
+		static tlf_internal function getTextLineTypographicAscent(textLine:TextLine, elem:FlowLeafElement,elemStart:int, textLineEnd:int, para:ParagraphElement):Number
+		{
+			CONFIG::debug { assert(elemStart == elem.getAbsoluteStart(),"bad elemStart passed to getTextLineTypographicAscent"); } 
+			var rslt:Number = textLine.getBaselinePosition(flash.text.engine.TextBaseline.ROMAN) - textLine.getBaselinePosition(flash.text.engine.TextBaseline.ASCENT);
+				
+			for (;;) 
+			{
+				if (elem is InlineGraphicElement)
+					rslt = Math.max(rslt,InlineGraphicElement(elem).getTypographicAscent(textLine));
+				elemStart += elem.textLength;
+				if (elemStart >= textLineEnd)
+					break;
+				elem = elem.getNextLeaf(para);
+				CONFIG::debug { assert(elem != null,"bad nextLeaf"); }
+			}
+			return rslt;
+		}
+        
+        //helper method to determine which subset of line is underlined
+        //I believe this will be replaced by the eventSink mechanism
+        private function isTextlineSubsetOfSpan(element:FlowLeafElement): Boolean
+        { 
+        	var spanStart:int = element.getAbsoluteStart();
+        	var spanEnd:int = spanStart + element.textLength;
+        	
+        	var lineStart:int = this.absoluteStart;
+        	var lineEnd:int = this.absoluteStart + this._textLength;
+          	
+        	return spanStart <= lineStart && spanEnd >= lineEnd;
+        }
+        
+       
+        
+ 		/** Create a rectangle for selection */
+		static private function createSelectionRect(selObj:Shape, color:uint, x:Number, y:Number, width:Number, height:Number):DisplayObject
+		{
+ 			selObj.graphics.beginFill(color);
+ 			var cmds:Vector.<int> = new Vector.<int>();
+ 			var pathPoints:Vector.<Number> = new Vector.<Number>();
+ 			
+ 			//set the start point - topLeft
+ 			cmds.push(GraphicsPathCommand.MOVE_TO);
+ 			pathPoints.push(x);
+ 			pathPoints.push(y);
+ 			
+ 			//line to topRight
+ 			cmds.push(GraphicsPathCommand.LINE_TO);
+ 			pathPoints.push(x + width);
+ 			pathPoints.push(y);
+ 			
+ 			//line to botRight
+ 			cmds.push(GraphicsPathCommand.LINE_TO);
+ 			pathPoints.push(x + width);
+ 			pathPoints.push(y + height);
+ 			
+ 			//line to botLeft
+ 			cmds.push(GraphicsPathCommand.LINE_TO);
+ 			pathPoints.push(x);
+ 			pathPoints.push(y + height);
+ 			
+ 			//line to close the path - topLeft
+ 			cmds.push(GraphicsPathCommand.LINE_TO);
+ 			pathPoints.push(x);
+ 			pathPoints.push(y);
+ 			
+ 			selObj.graphics.drawPath(cmds, pathPoints, flash.display.GraphicsPathWinding.NON_ZERO);
+ 			
+			return selObj;			
+		}
+	
+		/** @private getSelectionShapesCacheEntry
+		 * 
+		 * creates and adds block selection(s) to the text container.  In most circumstances,
+		 * this method will produce and add a single DisplayObject, but in certain circumstances,
+		 * such as TCY in TTB text, will need to make multiple selection rectangles.
+		 * 
+		 * Examples:
+		 * 1) horizontal - ABCDE
+		 * 2) vertical - ABCDE
+		 * 3) horizontal - ABcdE
+		 * 4) vertical:		A
+		 * 					B
+		 * 				   cde
+		 * 					F
+		 * 
+		 */
+		private function getSelectionShapesCacheEntry(begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine, blockProgression:String):SelectionCache
+		{
+			if (isDamaged())
+				return null;
+			
+			// CONFIG::debug { assert(_textLineCache != null, "bad call to getSelectionShapesCacheEntry"); }
+			
+			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
+			var paraAbsStart:int = _para.getAbsoluteStart();
+			
+			//if the indexes are identical and are equal to the start of the line, then
+			//don't draw anything.  This prevents a bar being drawn on a following line when
+			//selecting accross line boundaries
+			//with exception for a selection that includes just the first character of an empty last line in the TextFlow
+			if (begIdx == endIdx && paraAbsStart + begIdx == absoluteStart)
+			{
+				if (absoluteStart != _para.getTextFlow().textLength-1)
+					return null;
+				endIdx++;
+			}
+			
+			//the cached selection bounds and rects
+			var selectionCache:SelectionCache = _selectionBlockCache[this];
+			if (selectionCache && selectionCache.begIdx == begIdx && selectionCache.endIdx == endIdx)
+				return selectionCache;			
+			
+			var drawRects:Array = new Array();
+			//an array to store any tcy rectangles which need separate processing and may not exist
+			var tcyDrawRects:Array = new Array();
+			
+			if(selectionCache == null)
+			{
+				selectionCache = new SelectionCache();
+				_selectionBlockCache[this] = selectionCache;
+			}	
+			else
+			{
+				selectionCache.clear();
+			}
+			selectionCache.begIdx = begIdx;
+			selectionCache.endIdx = endIdx;
+			
+			var textLine:TextLine = getTextLine();
+			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
+			calculateSelectionBounds(textLine, drawRects, begIdx, endIdx, blockProgression, heightAndAdj);
+			
+			//iterate the blocks and create DisplayObjects to draw...
+			for each(var drawRect:Rectangle in drawRects)
+			{
+				CONFIG::debug{ assert(selectionCache != null, "If we're caching, selectionArray should never be null!"); }
+				//we have to make new rectangles or the convertLineRectToGlobal will alter the cached ones!
+				selectionCache.pushSelectionBlock(drawRect);
+			}
+			
+
+			//allow the atoms to be garbage collected.
+			if (textLine)
+				textLine.flushAtomData();
+			
+			return selectionCache;
+		}
+		
+		
+		/** @private - helper method to calculate all selection blocks within a line.*/
+		tlf_internal function calculateSelectionBounds(textLine:TextLine, rectArray:Array, begIdx:int, endIdx:int, blockProgression:String, heightAndAdj:Array):void
+		{
+			//the direction of the text
+			var direction:String = _para.computedFormat.direction;
+			//get the absolute start of the paragraph.  Calculation is expensive, so just do this once.
+			var paraAbsStart:int = _para.getAbsoluteStart();
+			//the current index.  used to iterate to the next element
+			var curIdx:int = begIdx;
+			//the current FlowLeafElement as determined by curIdx
+			var curElem:FlowLeafElement = null;
+			//the hightest glyph.  Needed to normalize the rectangles we'll be building
+			var largestRise:Number = 0;
+			
+			//blockRectArray holds each leaf's blocks which could be 1 or more
+			var blockRectArray:Array = new Array();
+			//floatRectArray holds the selection rects for any floats in the range.
+			var floatRectArray:Array = null;
+			//tcyDrawRects:Array
+			var tcyDrawRects:Array = null;
+			
+			//do this loop and only afterwards perform the normalization and addition to the rectArr
+			while(curIdx < endIdx)
+			{
+				curElem = _para.findLeaf(curIdx);
+				//if we somehow got a 0 length element, then increment the index and continue
+				if(curElem.textLength == 0)
+				{
+					++curIdx;
+					continue;
+				}
+				else if(curElem is InlineGraphicElement && (curElem as InlineGraphicElement).float != Float.NONE)
+				{
+					if(floatRectArray == null)
+						floatRectArray = new Array();
+						
+					var tempFloatArray:Array = makeSelectionBlocks(curIdx, curIdx+1, paraAbsStart, blockProgression, direction, heightAndAdj);
+					CONFIG::debug{ assert(tempFloatArray.length == 1, "How can a single floated InlineGraph have multiple shapes!"); }
+					floatRectArray.push(tempFloatArray[0]);
+					++curIdx;
+					continue;
+				}
+				//the number of potential glyphs to hilite.  Could larger than needs be if we are only selecting part of it.
+				var numCharsSelecting:int = curElem.textLength + curElem.getElementRelativeStart(_para) - curIdx;
+				//the index of the last glyph to hilite.  If a partial selection, use endIdx
+				var endPos:int = (numCharsSelecting + curIdx) > endIdx ? endIdx : (numCharsSelecting + curIdx);
+				
+				//if this is not a TCY in vertical, the blocks should all be running in the same direction
+				if (blockProgression != BlockProgression.RL || 
+					(textLine.getAtomTextRotation(textLine.getAtomIndexAtCharIndex(curIdx)) != TextRotation.ROTATE_0))
+				{
+					var leafBlockArray:Array = makeSelectionBlocks(curIdx, endPos, paraAbsStart, blockProgression, direction, heightAndAdj);
+					//copy all the blocks into the blockRectArray - we'll normalize them later
+					for(var leafBlockIter:int = 0; leafBlockIter < leafBlockArray.length; ++leafBlockIter)
+					{
+						blockRectArray.push(leafBlockArray[leafBlockIter]);
+					}
+				}
+				else
+				{
+					var tcyBlock:FlowElement = curElem.getParentByType(TCYElement);
+					CONFIG::debug{ assert(tcyBlock != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
+					
+					//if this element is still encompassed by a SubParagraphGroupElement of some kind (either a link or a TCYBlock)
+                	//keep moving up to the parent.  Otherwise, the below code will go into an infinite loop.  bug 1905734
+                	var tcyParentRelativeEnd:int = tcyBlock.parentRelativeEnd;
+                	var subParBlock:SubParagraphGroupElement = tcyBlock.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
+                	while (subParBlock)
+                	{
+                		tcyParentRelativeEnd += subParBlock.parentRelativeStart;
+                		subParBlock = subParBlock.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
+                	}
+					
+					var largestTCYRise:Number = 0;
+                    var lastTCYIdx:int = endIdx < tcyParentRelativeEnd ? endIdx : tcyParentRelativeEnd;
+                    var tcyRects:Array = new Array();
+
+			
+					while(curIdx < lastTCYIdx)
+					{
+						curElem = _para.findLeaf(curIdx);
+						numCharsSelecting = curElem.textLength + curElem.getElementRelativeStart(_para) - curIdx;
+						endPos = numCharsSelecting + curIdx > endIdx ? endIdx : numCharsSelecting + curIdx;
+						var tcyRectArray:Array =  makeSelectionBlocks(curIdx, endPos, paraAbsStart, blockProgression, direction, heightAndAdj);
+						
+						for(var tcyBlockIter:int = 0; tcyBlockIter < tcyRectArray.length; ++tcyBlockIter)
+						{
+							var tcyRect:Rectangle = tcyRectArray[tcyBlockIter];
+							
+							if(tcyRect.height > largestTCYRise)
+							{
+								largestTCYRise = tcyRect.height;
+							}
+								
+							tcyRects.push(tcyRect);
+						}
+						curIdx = endPos;
+					}
+					
+					if(!tcyDrawRects)
+						tcyDrawRects = new Array();
+						
+					normalizeRects(tcyRects, tcyDrawRects, largestTCYRise, BlockProgression.TB, direction);
+					continue;
+				
+				}
+				
+				//set the curIdx to the last char in the block
+				curIdx = endPos;
+			}
+			
+			
+			
+			//adding check for an empty set of draw rects.  If there are not recangles, skip this.
+			//this can happen is there are ONLY TCY blocks and the whole line is selected.
+			//Watson 2273832. - gak 02.09.09
+			//if the whole line is selected
+			if(blockRectArray.length > 0 && (paraAbsStart + begIdx) == absoluteStart && (paraAbsStart + endIdx) == (absoluteStart + textLength))
+			{
+				curElem = _para.findLeaf(begIdx);
+				//if we have the entire line selected, but the first element is NOT the last, then
+				//we will land up with a selection which is 1 character wider than it should be.
+				if(((curElem.getAbsoluteStart() + curElem.textLength) < (absoluteStart + textLength)) && endPos >= 2)
+				{
+					//make sure that this is a white char and that we aren't deselecting the last
+					//char in a line - esp important for scripts which don't use spaces ie Japanese
+					var charCode:int = _para.getCharCodeAtPosition(endPos - 1);
+					if(charCode != SpanElement.kParagraphTerminator.charCodeAt(0) && CharacterUtil.isWhitespace(charCode))
+					{
+						var lastElemBlockArray:Array = makeSelectionBlocks(endPos - 1, endPos - 1, paraAbsStart, blockProgression, direction, heightAndAdj);
+						var lastRect:Rectangle = lastElemBlockArray[lastElemBlockArray.length - 1];
+						var modifyRect:Rectangle = blockRectArray[blockRectArray.length - 1] as Rectangle;
+						
+						if (blockProgression != BlockProgression.RL)
+						{
+							//if they have the same width, simply remove the last block
+							if(modifyRect.width == lastRect.width)
+							{
+								blockRectArray.pop();
+							}
+							else
+							{
+								modifyRect.width -= lastRect.width;
+								
+								//if this is RTL, we need to shift the selection block over by the amount
+								//we reduced it.
+								if(direction == Direction.RTL)
+									modifyRect.left -= lastRect.width;
+							}
+						}
+						else
+						{
+							//if they have the same height, simply remove the last block
+							if(modifyRect.height == lastRect.height)
+							{
+								blockRectArray.pop();
+							}
+							else
+							{
+								modifyRect.height -= lastRect.height;
+								
+								//if this is RTL, we need to shift the selection block down by the amount
+								//we reduced it.
+								if(direction == Direction.RTL)
+									modifyRect.top += lastRect.height;
+							}
+						}
+					}
+				}
+			}
+			
+			normalizeRects(blockRectArray, rectArray, largestRise, blockProgression, direction);
+			//add in the TCY Rects
+			if(tcyDrawRects && tcyDrawRects.length > 0)
+			{
+				for(var tcyIter:int = 0; tcyIter < tcyDrawRects.length; ++tcyIter)
+				{
+					rectArray.push(tcyDrawRects[tcyIter]);
+				}
+			}
+			
+			//float selections do not normalize, put them into the rect array now
+			if(floatRectArray)
+			{
+				for(var floatIter:int = 0; floatIter < floatRectArray.length; ++floatIter)
+				{
+					rectArray.push(floatRectArray[floatIter]);
+				}
+			}
+			
+		}
+
+		private function createSelectionShapes(selObj:Shape, selFormat:SelectionFormat, container:DisplayObject, begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):void
+		{
+			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
+			CONFIG::debug { assert(contElement != null,"para with no container"); }
+			var blockProgression:String = contElement.computedFormat.blockProgression;
+			
+			var selCache:SelectionCache = getSelectionShapesCacheEntry(begIdx, endIdx, prevLine, nextLine, blockProgression);
+			if (!selCache)
+				return;
+		
+			//iterate the blocks and create DisplayObjects to draw...
+			var drawRect:Rectangle;
+			var color:uint = selFormat.rangeColor;
+			
+			if (_para && _para.getTextFlow()) {
+				var selMgr:ISelectionManager = _para.getTextFlow().interactionManager;
+				if (selMgr && (selMgr.anchorPosition == selMgr.activePosition))
+					color = selFormat.pointColor;
+			}
+			
+			for each (drawRect in selCache.selectionBlocks)
+			{
+				drawRect = drawRect.clone();
+				convertLineRectToContainer(drawRect, true);
+				createSelectionRect(selObj, color, drawRect.x, drawRect.y, drawRect.width, drawRect.height);
+			}
+		}
+		
+ 		/** @private 
+		 * Get the height and vertical adjustment for the line's selection shape, assuming Western typographic rules
+		 * where leading is included in selection.
+		 * @return An array with two elements
+		 * [0] height
+		 * [1] vertical adjustment to counter 'align bottom' behavior. The remainder of the selection code assumes selection shape
+		 * bottom is to be aligned with line descent. If this is not the case, vertical adjustment is set to an appropriate non-zero value. 
+		 */
+ 		tlf_internal function getRomanSelectionHeightAndVerticalAdjustment (prevLine:TextFlowLine, nextLine:TextFlowLine):Array
+ 		{	
+ 			var rectHeight:Number = 0;
+ 			var verticalAdj:Number = 0; //  Default to 'align bottom'.
+ 			
+			//This code erroneously assumed that it would only be called with a SPACE justifier and that AUTO would be up.  That is incorrect
+			//because some scripts, like Korean, use an up leading model and the EAST_ASIAN justifier.  New code just performs the check
+ 			if(ParagraphElement.useUpLeadingDirection(_para.getEffectiveLeadingModel()))
+ 			{			
+ 				// "Space above, align bottom" 
+ 				// 1) Space above as dictated by first baseline offset for the first line or line leading otherwise (both obtained from the 'height' data member)
+ 				// 2) Selection rectangle must at least include all of the text area
+ 				rectHeight = height > _textHeight ? height : _textHeight;
+ 				
+ 				// 3) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
+ 			}
+ 			else
+ 			{
+ 				// TODO-9/4/08-Is this the right way to check for first/last lines? 
+				var isFirstLine:Boolean = !prevLine || prevLine.controller != controller || prevLine.columnIndex != columnIndex;
+				var isLastLine:Boolean  = !nextLine || nextLine.controller != controller || nextLine.columnIndex != columnIndex
+						|| nextLine.paragraph.getEffectiveLeadingModel() == LeadingModel.ROMAN_UP;
+ 					//I'm removing this line as it makes the assumption that AUTO leading dir is UP only for Roman text, which is incorrect.
+ 					//Korean also uses UP leading but uses the EastAsian justifier. - gak 01.22.09
+ 					//||(nextLine.paragraph.computedFormat.leadingDirection == LeadingDirection.AUTO && nextLine.paragraph.computedFormat.justificationRule == JustificationRule.SPACE); 
+
+ 				if (isLastLine)
+ 				{
+ 					// There is no line after this one, or there is one which uses leading UP, so leading DOWN does not apply
+ 							
+ 					if (!isFirstLine)
+ 					{
+ 						// "Space above None, align bottom" (eqivalently, "Space below None, align top"): 
+ 						// 1) Only the text area should be selected
+ 						rectHeight = _textHeight;
+ 		
+ 						// 2) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
+ 					}
+ 					else
+ 					{
+ 						// "Space above, align bottom" 
+ 						// 1) Space above as dictated by first baseline offset 
+ 						// 2) Selection rectangle must at least include all of the text area
+ 						rectHeight = height > _textHeight ? height : _textHeight;
+ 						// 3) Selection rectangle's bottom aligned with line descent; verticalAdj remains 0
+ 					}
+ 				}
+ 				else
+ 				{
+ 					 // There is a line after this one, so leading DOWN applies
+ 					 
+ 					if (!isFirstLine)
+ 					{
+ 						// "Space below, align top" 
+ 						// 1) Space below as dictated by line leading (obtained from 'height' member of next line) 
+ 						// 2) Selection rectangle must at least include all of the text area
+ 						rectHeight = nextLine.height > _textHeight ? nextLine.height : _textHeight;
+ 						
+ 						// 3) Selection rectangle's top to be aligned with line ascent, so its bottom to be at rectHeight - textLine.ascent,
+ 						// not textLine.descent, set verticalAdj accordingly 
+ 						verticalAdj = rectHeight - _textHeight; // same as rectHeight - textLine.ascent - textLine.descent
+ 					}
+ 					else
+ 					{
+ 						// Union of 
+ 						// 1) first line, leading up: In this case, rectangle height is the larger of line height and text height,
+ 						// and the rectangle is shifted down by descent amount to align bottoms. So, top of rectangle is at:
+ 						var top:Number = _descent - (height > _textHeight ? height : _textHeight);
+ 						
+ 						// 2) interior line, leading down: In this case, rectangle height is the larger of line leading and text height,
+ 						// and the rectangle is shifted up by ascent amount to align tops. So, bottom of rectangle is at:
+ 						var bottom:Number = (nextLine.height > _textHeight ? nextLine.height : _textHeight) - _ascent;
+ 						
+ 						rectHeight = bottom - top;
+ 						
+ 						// 3) Selection rectangle's bottom to be at 'bottom', not the line's descent; set verticalAdj accordingly
+ 						verticalAdj = bottom - _descent;
+ 					}
+ 				}
+ 			}
+ 			
+ 			//If we don't have a line above us, then we need to pad the line a bit as well as make it shift up.
+ 			//If we don't, then it overlaps the line below too much OR clips the top of the glyphs.
+ 			if(!prevLine || prevLine.columnIndex != this.columnIndex || prevLine.controller != this.controller)
+ 			{
+ 				//make it taller - this is kinda a fudge, but we have no info to determine a good top.
+ 				//if we don't do this, the selection rectangle will clip to the top of the glyphs and even
+ 				//let parts stick out a bit.  So, re-add the descent and offset the rect by 50% so that
+ 				//it appears to balance the top and bottom.
+ 				rectHeight += this.descent;
+ 				verticalAdj = Math.floor(this.descent/2);
+ 			}
+ 			return [rectHeight, verticalAdj];
+ 		}
+		
+		/** @private 
+		 * 
+		 * 
+		 */
+		 private function makeSelectionBlocks(begIdx:int, endIdx:int, paraAbsStart:int, blockProgression:String, direction:String, heightAndAdj:Array):Array
+		 {
+		 	CONFIG::debug{ assert(begIdx <= endIdx, "Selection indexes are reversed!  How can this happen?!"); }
+		 	
+		 	var blockArray:Array = new Array();
+		 	var blockRect:Rectangle = new Rectangle();
+		 	var startElem:FlowLeafElement = _para.findLeaf(begIdx);
+			var startMetrics:Rectangle = startElem.getComputedFontMetrics().emBox;
+			
+			var textLine:TextLine = getTextLine(true);
+
+			//++makeBlockPassCounter;
+		 	//trace(makeBlockPassCounter + ") direction = " + direction + " blockProgression = " + blockProgression);
+				 	
+		 	//if this is the whole line, then we should use line data to perform the selection
+			if(paraAbsStart + begIdx == absoluteStart && paraAbsStart + endIdx == absoluteStart + textLength)
+			{
+				var globalStart:Point = new Point(0,0);
+				var justRule:String = _para.getEffectiveJustificationRule();
+				
+				//use the textLine info if we're not using J justification
+				if(justRule != JustificationRule.EAST_ASIAN)
+				{
+					if(blockProgression == BlockProgression.RL)
+					{
+						globalStart.x -= heightAndAdj[1];
+						blockRect.width = heightAndAdj[0];
+						blockRect.height = textLine.textWidth == 0 ? EMPTY_LINE_WIDTH : textLine.textWidth;
+					}
+					else 
+					{
+						globalStart.y += heightAndAdj[1];
+						blockRect.height = heightAndAdj[0];
+						blockRect.width = textLine.textWidth == 0 ? EMPTY_LINE_WIDTH : textLine.textWidth;
+					}	
+					
+				}
+				else
+				{
+					var eaStartElem:int  = textLine.getAtomIndexAtCharIndex(begIdx);
+					var eaStartRect:Rectangle = textLine.getAtomBounds(eaStartElem);
+					
+					if(blockProgression == BlockProgression.RL)
+					{
+						blockRect.width = eaStartRect.width;
+						blockRect.height = textLine.textWidth;
+					}
+					else
+					{
+						blockRect.height =  eaStartRect.height;
+						blockRect.width = textLine.textWidth;
+					}
+				}
+				
+				blockRect.x = globalStart.x;
+				blockRect.y = globalStart.y;
+				
+				if(blockProgression == BlockProgression.RL)
+				{
+					blockRect.x -= textLine.descent;
+				}
+				else
+				{
+					blockRect.y += (textLine.descent - blockRect.height)
+				}
+				
+				//handle rotation
+				if(startElem.computedFormat.textRotation == TextRotation.ROTATE_180 || 
+					startElem.computedFormat.textRotation == TextRotation.ROTATE_90)
+				{
+					if(blockProgression != BlockProgression.RL)
+						blockRect.y += blockRect.height / 2;
+					else
+						blockRect.x -= blockRect.width;
+				}
+				//push it onto array
+				blockArray.push(blockRect);
+			}
+			else //we only have part of the line.  Get the start and end TC bounds
+			{
+				//trace(makeBlockPassCounter + ") begIdx = " + begIdx.toString() + " endIdx = " +  endIdx.toString());
+				var begElementIndex:int = textLine.getAtomIndexAtCharIndex(begIdx); 
+				var endElementIndex:int = adjustEndElementForBidi(begIdx, endIdx, begElementIndex, direction);
+				
+				//trace(makeBlockPassCounter + ") begElementIndex = " + begElementIndex.toString() + " endElementIndex = " +  endElementIndex.toString());
+				CONFIG::debug{ assert(begElementIndex >= 0, "Invalid start index! begIdx = " + begIdx)};
+				CONFIG::debug{ assert(endElementIndex >= 0, "Invalid end index! begIdx = " + endIdx)};
+				
+				if(direction == Direction.RTL && textLine.getAtomBidiLevel(endElementIndex)%2 != 0)
+				{
+					//if we are in RTL, anchoring the LTR text gets tricky.  Because the endElement is before the first
+					//element - which is why we're in this code - the result can be a zero-width rectangle if the span of LTR
+					//text breaks across line boundaries.  If that is the case, then the endElementIndex value will be 0.  As
+					//this is the less common case, assume that it isn't and make all other cases come first
+					if (endElementIndex == 0 && begIdx < endIdx-1)
+					{
+						//since the endElementIndex is 0, meaning that the LTR spans lines,
+						//we want to grab the glyph before the endIdx which represents the last LTR glyph for the selection. 
+						//Make a recursive call into makeSelectionBlocks using and endIdx decremented by 1.
+						blockArray = makeSelectionBlocks(begIdx, endIdx - 1, paraAbsStart, blockProgression, direction, heightAndAdj);
+						var bidiBlock:Array = makeSelectionBlocks(endIdx - 1, endIdx - 1, paraAbsStart, blockProgression, direction, heightAndAdj)
+						var bidiBlockIter:int = 0;
+						while(bidiBlockIter < bidiBlock.length)
+						{
+							blockArray.push(bidiBlock[bidiBlockIter]);
+							++bidiBlockIter;
+						}
+						return blockArray;
+					}
+				}
+				
+				var begIsBidi:Boolean = begElementIndex != -1 ? isAtomBidi(begElementIndex, direction) : false;
+				var endIsBidi:Boolean = endElementIndex != -1 ? isAtomBidi(endElementIndex, direction) : false;
+				
+			 	//trace("begElementIndex is bidi = " + begIsBidi.toString());
+				//trace("endElementIndex is bidi = " + endIsBidi.toString());	
+				
+				if(begIsBidi || endIsBidi)
+				{	
+					//this code needs to iterate over the glyphs starting at the begElementIndex and going forward.
+					//It doesn't matter is beg is bidi or not, we need to find a boundary, create a rect on it, then proceded.
+					//use the value of begIsBidi for testing the consistency of the selection.
+					
+					//Example bidi text.  Note that the period comes at the left end of the line:
+					//
+					//	Bidi state:		f f t t t t t	(true/false)
+					//	Element Index:0 1 2 3 4 5 6		(0 is the para terminator)
+					//	Chars:			. t o _ b e
+					//  Flow Index:	   6 0 1 2 3 4 (5) 	Note that these numbers represent the space between glyphs AND
+					//					 5(f)			that index 5 is both the space after the e and before the period.
+					//									but, the position 5 is not a valid cursor location.
+					
+					//the original code I implemented used the beg and endElement indexes however that fails because when the text
+					//is mixed bidi/non-bidi, the indexes are only 1 char apart. This resulted in, for example, only the period in 
+					//a line getting selected when the text was bidi.   Instead, we're going to use the begIdx and endIdx and 
+					//recalculate the element indexes each time.  This is expensive, but I don't see an alternative. - gak 09.05.08
+					var curIdx:int = begIdx;
+					var incrementor:int = (begIdx != endIdx ? 1 : 0);
+					
+					//the indexes used to draw the seleciton.  activeStart/End represent the
+					//beginning of the selection shape atoms, while cur is the one we are testing.
+					var activeStartIndex:int = begElementIndex;
+					var activeEndIndex:int = begElementIndex;
+					var curElementIndex:int = begElementIndex;
+					
+					//when activeEndIsBidi no longer matches the bidi setting for the activeStartIndex, we will create the shape
+					var activeEndIsBidi:Boolean = begIsBidi;
+					
+					do
+					{
+						//increment the index
+						curIdx += incrementor;
+						//get the next atom index
+						curElementIndex = textLine.getAtomIndexAtCharIndex(curIdx);
+						
+						//calculate the bidi level for the - kinda cludgy, but if the bidi-text wraps, curElementIndex == -1
+						//so just set it to false if this is the case.  It will get ignored in the subsequent check and curIdx
+						//will == endIdx as this is the last glyph in the line - which is why the next is -1 - gak 09.12.08
+						var curIsBidi:Boolean = (curElementIndex != -1) ? isAtomBidi(curElementIndex, direction) : false;
+							
+						if(curElementIndex != -1 && curIsBidi != activeEndIsBidi)
+						{
+							blockRect = makeBlock(activeStartIndex, activeEndIndex, startMetrics, blockProgression, direction, heightAndAdj);
+							blockArray.push(blockRect);
+							
+							//shift the activeStart/End indexes to the current
+							activeStartIndex = curElementIndex;
+							activeEndIndex = curElementIndex;
+							//update the bidi setting
+							activeEndIsBidi = curIsBidi;
+						}
+						else
+						{
+							//we don't get another chance to make a block, so if this is the last char, make the block before we bail out.
+							//we have to check both equality and equality plus the incrementor because if we don't, then we'll miss a
+							//character in the selection.
+							if(curIdx == endIdx)
+							{
+								blockRect = makeBlock(activeStartIndex, activeEndIndex, startMetrics, blockProgression, direction, heightAndAdj);
+								blockArray.push(blockRect);
+							}
+							
+							activeEndIndex = curElementIndex;
+						}
+					}while(curIdx < endIdx)
+					
+				}
+				else
+				{
+					var testILG:InlineGraphicElement = startElem as InlineGraphicElement;
+					if(!testILG || testILG.float == Float.NONE)
+					{
+						blockRect = makeBlock(begElementIndex, endElementIndex, startMetrics, blockProgression, direction, heightAndAdj);
+					}
+					else
+					{
+						blockRect = testILG.graphic.getBounds(textLine);
+					}
+					
+					blockArray.push(blockRect);
+				}
+				
+			}
+			
+			return blockArray;
+		 }	
+		 
+		/** @private 
+		 * 
+		 * 
+		 */
+		 private function makeBlock(begElementIndex:int, endElementIndex:int, startMetrics:Rectangle, blockProgression:String, direction:String, heightAndAdj:Array):Rectangle
+		 {
+		 	var blockRect:Rectangle = new Rectangle();
+			var globalStart:Point = new Point(0,0);
+			var heightAndAdj:Array;
+			
+			if(begElementIndex > endElementIndex)
+			{
+				// swap the start and end
+				var tempEndIdx:int = endElementIndex;
+				endElementIndex = begElementIndex;
+				begElementIndex = tempEndIdx;
+			}
+			var textLine:TextLine = getTextLine(true);
+			
+			//now that we have elements and they are in the right order for drawing, get their rectangles
+			var begCharRect:Rectangle = textLine.getAtomBounds(begElementIndex);
+			//trace(makeBlockPassCounter + ") begCharRect = " + begCharRect.toString());
+			
+			var endCharRect:Rectangle = textLine.getAtomBounds(endElementIndex);
+			//trace(makeBlockPassCounter + ") endCharRect = " + endCharRect.toString());
+			
+			//Calculate the justificationRule value
+			var justRule:String = _para.getEffectiveJustificationRule();
+			//If this is TTB text and NOT TCY, as indicated by TextRotation.rotate0...
+			if(blockProgression == BlockProgression.RL && textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
+			{
+				globalStart.y = begCharRect.y;
+				blockRect.height = begElementIndex != endElementIndex ? endCharRect.bottom - begCharRect.top : begCharRect.height;
+				
+				//re-ordered this code.  EAST_ASIAN is more common in vertical and should be the first option.
+				if(justRule == JustificationRule.EAST_ASIAN)
+				{
+					blockRect.width = begCharRect.width;
+				}
+				else
+				{
+					blockRect.width = heightAndAdj[0];
+					globalStart.x -= heightAndAdj[1];
+				}
+			}
+			else
+			{
+				//given bidi text alternations, the endCharRect could be left of the begCharRect,
+				//use whichever is farther left.
+				globalStart.x = (begCharRect.x < endCharRect.x ? begCharRect.x : endCharRect.x);
+				//if we're here and the BlockProgression is TTB, then we're TCY.  Less frequent case, so make non-TCY
+				//the first option...
+				//NB - Never use baseline adjustments for TCY.  They don't make sense here.(I think) - gak 06.03.08
+				if(blockProgression == BlockProgression.RL)
+					globalStart.y = begCharRect.y + (startMetrics.width /2); // TODO-9/5/8:Behavior for leading down TBD
+				
+				
+				if(justRule != JustificationRule.EAST_ASIAN)
+				{
+					blockRect.height = heightAndAdj[0];
+					if(blockProgression == BlockProgression.RL)
+						globalStart.x -= heightAndAdj[1];
+					else 
+						globalStart.y += heightAndAdj[1];
+					//changed the width from a default of 2 to use the begCharRect.width so that point seletion
+					//can choose to use the right or left side of the glyph when drawing a caret Watson 1876415/1876953- gak 08.19.09
+					blockRect.width = begElementIndex != endElementIndex ? Math.abs(endCharRect.right - begCharRect.left) : begCharRect.width;
+				}
+				else
+				{
+					blockRect.height =  begCharRect.height;
+						
+					//changed the width from a default of 2 to use the begCharRect.width so that point seletion
+					//can choose to use the right or left side of the glyph when drawing a caret Watson 1876415/1876953- gak 08.19.09
+					blockRect.width = begElementIndex != endElementIndex ? Math.abs(endCharRect.right - begCharRect.left) : begCharRect.width;
+				}
+			}
+			
+			blockRect.x = globalStart.x;
+			blockRect.y = globalStart.y;
+			if(blockProgression == BlockProgression.RL)
+			{
+				if(textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
+					blockRect.x -= textLine.descent;
+				else //it's TCY
+					blockRect.y -= (blockRect.height / 2)
+			}
+			else
+			{
+				blockRect.y += (textLine.descent - blockRect.height);
+			}
+			
+			var tfl:TextFlowLine = textLine.userData as TextFlowLine;
+			var curElem:FlowLeafElement = _para.findLeaf(textLine.textBlockBeginIndex + begElementIndex);
+			var rotation:String = curElem.computedFormat.textRotation;
+			
+			//handle rotation.  For horizontal text, rotations of 90 or 180 cause the text
+			//to draw under the baseline in a cosistent location.  Vertical text is a bit more complicated
+			//in that a 90 rotation puts it immediately to the left of the Em Box, whereas 180 is one quarter
+			//of the way in the Em Box. Fix for Watson 1915930 - gak 02.17.09
+			if(rotation == TextRotation.ROTATE_180 || 
+				rotation == TextRotation.ROTATE_90)
+			{
+				if(blockProgression != BlockProgression.RL)
+					blockRect.y += (blockRect.height / 2);
+				else
+				{
+					if(curElem.getParentByType(TCYElement) == null)
+					{	
+						if(rotation == TextRotation.ROTATE_90)
+							blockRect.x -= blockRect.width;
+						else
+							blockRect.x -= (blockRect.width * .75);
+					}
+					else
+					{
+						if(rotation == TextRotation.ROTATE_90)
+							blockRect.y += blockRect.height;
+						else
+							blockRect.y += (blockRect.height * .75);
+					}
+				}
+			}
+			
+			
+			return blockRect;
+		 }
+		 
+		/** @private
+		 * 
+		 * 
+		 */
+		tlf_internal function convertLineRectToContainer(rect:Rectangle, constrainShape:Boolean):void
+		{
+			var textLine:TextLine = getTextLine();
+			
+			/* var globalStart:Point = new Point(rect.x, rect.y);
+
+		 	//convert to controller coordinates...
+			////trace(makeBlockPassCounter + ") globalStart = " + globalStart.toString());
+			globalStart = textLine.localToGlobal(globalStart);
+			////trace(makeBlockPassCounter + ") localToGlobal.globalStart = " + globalStart.toString());
+			globalStart = container.globalToLocal(globalStart);
+			////trace(makeBlockPassCounter + ") globalToLocal.globalStart = " + globalStart.toString());
+			rect.x = globalStart.x;
+			rect.y = globalStart.y; */
+			
+			// this is much simpler and actually more accurate - localToGlobal/globalToLocal does some rounding
+			rect.x += textLine.x;
+			rect.y += textLine.y;
+			
+			if (constrainShape)
+			{
+				var tf:TextFlow = _para.getTextFlow();
+				var columnRect:Rectangle = controller.columnState.getColumnAt(this.columnIndex);
+				constrainRectToColumn(tf,rect,columnRect,controller.horizontalScrollPosition,controller.verticalScrollPosition,controller.compositionWidth,controller.compositionHeight);
+			}
+		}
+		
+		/** @private */
+		static tlf_internal function constrainRectToColumn(tf:TextFlow,rect:Rectangle,columnRect:Rectangle,hScrollPos:Number,vScrollPos:Number,compositionWidth:Number,compositionHeight:Number):void
+		{		
+			if(tf.computedFormat.lineBreak == LineBreak.EXPLICIT)
+				return;
+					
+			var bp:String = tf.computedFormat.blockProgression;
+			var direction:String = tf.computedFormat.direction;
+
+			if(bp == BlockProgression.TB && !isNaN(compositionWidth))
+			{	
+				if(direction == Direction.LTR)
+				{
+					//make sure is doesn't go past the end of the container
+					if(rect.left > (columnRect.x + columnRect.width + hScrollPos))
+						rect.left = (columnRect.x + columnRect.width + hScrollPos);
+					
+					//make sure that if this is a selection and not a point selection, that 
+					//we don't go beyond the end of the container...
+					if(rect.right > (columnRect.x + columnRect.width + hScrollPos))
+						rect.right = (columnRect.x + columnRect.width + hScrollPos);
+				}
+				else
+				{
+					if(rect.right < (columnRect.x + hScrollPos))
+						rect.right = (columnRect.x + hScrollPos);
+						
+					if(rect.left < (columnRect.x + hScrollPos))
+						rect.left = (columnRect.x + hScrollPos);
+				}
+			}
+			else if (bp == BlockProgression.RL && !isNaN(compositionHeight))
+			{
+				if(direction == Direction.LTR)
+				{
+					//make sure is doesn't go past the end of the container
+					if(rect.top > (columnRect.y + columnRect.height + vScrollPos))
+						rect.top = (columnRect.y + columnRect.height + vScrollPos);
+					
+					//make sure that if this is a selection and not a point selection, that 
+					//we don't go beyond the end of the container...
+					if(rect.bottom > (columnRect.y + columnRect.height + vScrollPos))
+						rect.bottom = (columnRect.y + columnRect.height + vScrollPos);
+				}
+				else
+				{
+					if(rect.bottom < (columnRect.y + vScrollPos))
+						rect.bottom = (columnRect.y + vScrollPos);
+						
+					if(rect.top < (columnRect.y + vScrollPos))
+						rect.top = (columnRect.y + vScrollPos);
+				}
+			}
+		}
+		 
+		/** @private
+		 * Helper method to hilight the portion of a block selection on this TextLine.  A selection display is created and added to the line's TextFrame with ContainerController addSelectionShape.
+		 * @param begIdx absolute index of start of selection on this line.
+		 * @param endIdx absolute index of end of selection on this line.
+		 */
+		tlf_internal function hiliteBlockSelection(selObj:Shape, selFormat:SelectionFormat, container:DisplayObject, begIdx:int,endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):void
+		{
+			// no container for overflow lines, or lines scrolled out 
+			if (isDamaged() || !_controller)
+				return;
+
+			// CONFIG::debug { assert(_textLineCache != null, "bad call to hiliteBlockSelection"); }
+	
+			var textLine:TextLine = peekTextLine();
+			if (!textLine || !textLine.parent)
+				return;
+								
+			var paraStart:int = _para.getAbsoluteStart();
+			begIdx -= paraStart;
+			endIdx -= paraStart;
+			
+			createSelectionShapes(selObj, selFormat, container, begIdx, endIdx, prevLine, nextLine);
+		} 
+		
+		/** @private
+		 * Helper method to hilight a point selection on this TextLine.  x,y,w,h of the selection are calculated and ContainerController.drawPointSelection is called 
+		 * @param idx absolute index of the point selection.
+		 */
+		tlf_internal function hilitePointSelection(selFormat:SelectionFormat, idx:int, container:DisplayObject, prevLine:TextFlowLine, nextLine:TextFlowLine):void
+		{
+			var rect:Rectangle = computePointSelectionRectangle(idx,container,prevLine,nextLine, true);
+			if (rect)
+				_controller.drawPointSelection(selFormat, rect.x, rect.y, rect.width, rect.height)
+		}
+		
+		static private function setRectangleValues(rect:Rectangle,x:Number,y:Number,width:Number,height:Number):void
+		{
+			rect.x = x;
+			rect.y = y;
+			rect.width = width;
+			rect.height = height;
+		}
+		/** @private */		
+		tlf_internal function computePointSelectionRectangle(idx:int, container:DisplayObject, prevLine:TextFlowLine, nextLine:TextFlowLine, constrainSelRect:Boolean):Rectangle
+		{
+			if (isDamaged() || !_controller)
+				return null;
+
+			// CONFIG::debug { assert(_textLineCache != null, "bad call to hiliteBlockSelection"); }
+	
+			// no container for overflow lines, or lines scrolled out 
+			var textLine:TextLine = peekTextLine();
+			if (!textLine || !textLine.parent)
+				return null;			
+			// adjust to this paragraph's TextBlock
+			idx -= _para.getAbsoluteStart();
+
+			textLine = getTextLine(true);
+			
+			//endIdx will only differ if idx is altered when detecting TCY bounds
+			var endIdx:int = idx;
+			var elementIndex:int = textLine.getAtomIndexAtCharIndex(idx);
+			CONFIG::debug{ assert(elementIndex != -1, "Invalid point selection index! idx = " + idx); }
+			
+			var isTCYBounds:Boolean = false;
+			var paraLeadingTCY:Boolean = false;
+			
+			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
+			CONFIG::debug { assert(contElement != null,"para with no container"); }
+			var blockProgression:String = contElement.computedFormat.blockProgression;
+			var direction:String = _para.computedFormat.direction;
+			
+			//need to check for TCY.  TCY cannot take input into it's head, but can in it's tail.
+			if(blockProgression == BlockProgression.RL)
+			{
+				if (idx == 0)
+				{ 
+					if(textLine.getAtomTextRotation(0) == TextRotation.ROTATE_0)
+						paraLeadingTCY = true;
+				}
+				else
+				{
+					var prevElementIndex:int = textLine.getAtomIndexAtCharIndex(idx - 1);
+					if(prevElementIndex != -1)
+					{
+						//if this elem is TCY, then we need to back up one space and use the right bounds
+						if(textLine.getAtomTextRotation(elementIndex) == TextRotation.ROTATE_0 && 
+							textLine.getAtomTextRotation(prevElementIndex) != TextRotation.ROTATE_0)
+						{
+							elementIndex = prevElementIndex;
+							--idx;
+							isTCYBounds = true;
+						}
+						else if(textLine.getAtomTextRotation(prevElementIndex) == TextRotation.ROTATE_0)
+						{
+							elementIndex = prevElementIndex;
+							--idx;
+							isTCYBounds = true;
+						}
+					}
+				}
+			}
+			
+			var heightAndAdj:Array = getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
+			var blockRectArray:Array = makeSelectionBlocks(idx, endIdx, _para.getAbsoluteStart(), blockProgression, direction, heightAndAdj);
+			CONFIG::debug{ assert(blockRectArray.length == 1, "A point selection should return a single selection rectangle!"); }
+			var rect:Rectangle = blockRectArray[0];
+			
+			convertLineRectToContainer(rect, constrainSelRect);
+			
+			var drawOnRight:Boolean = (direction == Direction.RTL);
+				
+			if((drawOnRight && textLine.getAtomBidiLevel(elementIndex) % 2 == 0) || 
+				(!drawOnRight && textLine.getAtomBidiLevel(elementIndex) % 2 != 0))
+			{
+				drawOnRight = !drawOnRight;
+			}
+			
+			if(blockProgression == BlockProgression.RL && textLine.getAtomTextRotation(elementIndex) != TextRotation.ROTATE_0)
+			{
+				if(!drawOnRight)
+					setRectangleValues(rect, rect.x, !isTCYBounds ? rect.y : rect.y + rect.height,rect.width,1);
+				else
+					setRectangleValues(rect, rect.x, !isTCYBounds ? rect.y + rect.height : rect.y ,rect.width,1);
+			}
+			else
+			{
+				//choose to use the right or left side of the glyph based on Direction when drawing a caret Watson 1876415/1876953
+				//if the direction is ltr, then the cursor should be on the left side
+				if(!drawOnRight)
+					setRectangleValues(rect, !isTCYBounds ? rect.x : rect.x + rect.width, rect.y, 1, rect.height);
+				else //otherwise, it should be on the right, unless it is TCY
+					setRectangleValues(rect, !isTCYBounds ? rect.x + rect.width : rect.x, rect.y, 1, rect.height);
+			}
+				
+			//allow the atoms to be garbage collected.
+			textLine.flushAtomData();
+			
+			return rect;
+  		}
+  		
+  		/** @private
+  		 * Three states.  Disjoint(0), Intersects(1), HeightContainedIn(2),  
+  		 */
+  		 
+  		tlf_internal function selectionWillIntersectScrollRect(scrollRect:Rectangle, begIdx:int, endIdx:int, prevLine:TextFlowLine, nextLine:TextFlowLine):int
+  		{
+  			var contElement:ContainerFormattedElement = _para.getAncestorWithContainer();
+			CONFIG::debug { assert(contElement != null,"para with no container"); }
+			var blockProgression:String = contElement.computedFormat.blockProgression;
+			var textLine:TextLine = getTextLine(true);
+			
+  			if (begIdx == endIdx)
+  			{
+  				var pointSelRect:Rectangle = computePointSelectionRectangle(begIdx, DisplayObject(controller.container), prevLine, nextLine, false);
+  				if (pointSelRect)
+  				{
+  					if (scrollRect.containsRect(pointSelRect))
+  						return 2;
+	  				if (scrollRect.intersects(pointSelRect))
+	  					return 1;
+	  			}
+  			}
+  			else
+  			{
+				var paraStart:int = _para.getAbsoluteStart();
+  				var selCache:SelectionCache = this.getSelectionShapesCacheEntry(begIdx-paraStart,endIdx-paraStart,prevLine,nextLine,blockProgression);
+  				if (selCache)
+  				{
+  					//iterate the blocks and check for intersections
+					var drawRect:Rectangle;
+					for each (drawRect in selCache.selectionBlocks)
+					{
+						drawRect = drawRect.clone();
+						// convertLineRectToContainer(container, drawRect);
+						drawRect.x += textLine.x; 
+						drawRect.y += textLine.y; 
+						if (scrollRect.intersects(drawRect))
+						{
+							if(blockProgression == BlockProgression.RL)
+							{
+								// see if width is entirely contained in scrollRect
+								if (drawRect.left >= scrollRect.left && drawRect.right <= scrollRect.right)
+									return 2;
+							}
+							else
+							{
+								if (drawRect.top >= scrollRect.top && drawRect.bottom <= scrollRect.bottom)
+									return 2;
+							}
+							return 1;
+						}
+					}
+  				}
+  			}
+  			return 0;
+  		}
+  		
+
+		/** @private */
+		CONFIG::debug private static function dumpAttribute(result:String, attributeName:String, attributeValue:Object):String
+		{
+			if (attributeValue)
+			{
+				result += " ";
+				result += attributeName;
+				result += "=\"";
+				result += attributeValue.toString();
+				result += "\""	
+			}
+			return result;		
+		}
+		
+		/** @private
+		 */
+		private function normalizeRects(srcRects:Array, dstRects:Array, largestRise:Number, blockProgression:String, direction:String):void
+		{
+			//the last rectangle in the list with a potential to merge
+			var lastRect:Rectangle = null;
+			var rectIter:int = 0;
+			while(rectIter < srcRects.length)
+			{
+				//get the current rect and advance the iterator
+				var rect:Rectangle = srcRects[rectIter++];
+				
+				//apply a new height if needed.
+				if(blockProgression == BlockProgression.RL)
+				{
+					if(rect.width < largestRise)
+					{
+						rect.width = largestRise;
+					}
+				}
+				else
+				{
+					if(rect.height < largestRise)
+					{
+						rect.height = largestRise;
+					}
+				}
+				//if the lastRect is null, no need to perform calculation
+				if(lastRect == null)
+				{
+					lastRect = rect;
+				}
+				else
+				{
+					//TCY has already been excluded, so no need to worry about it here...
+					if(blockProgression == BlockProgression.RL)
+					{
+						//trace(normalCounter + ") lastRect = " + lastRect.toString());
+						//trace(normalCounter + ") rect = " + rect.toString());
+						
+						//merge it in to the last rect
+						if(lastRect.y < rect.y && (lastRect.y + lastRect.height) >= rect.top && lastRect.x == rect.x)
+						{
+							lastRect.height += rect.height;
+						}
+						else if(rect.y < lastRect.y && lastRect.y <= rect.bottom && lastRect.x == rect.x)
+						{
+							lastRect.height += rect.height;
+							lastRect.y = rect.y;
+						}
+						else
+						{
+							//we have a break in the rectangles and should push last rect onto the draw list before continuing
+							dstRects.push(lastRect);
+							lastRect = rect;
+						}
+					}
+					else
+					{
+						if(lastRect.x < rect.x && (lastRect.x + lastRect.width) >= rect.left && lastRect.y == rect.y)
+						{
+							lastRect.width += rect.width;
+						}
+						else if(rect.x < lastRect.x && lastRect.x <= rect.right && lastRect.y == rect.y)
+						{
+							lastRect.width += rect.width;
+							lastRect.x = rect.x;
+						}
+						else
+						{
+							//we have a break in the rectangles and should push last rect onto the draw list before continuing
+							dstRects.push(lastRect);
+							lastRect = rect;
+						}
+					}
+				}
+				//if this is the last rectangle, we haven't added it, do so now.
+				if(rectIter == srcRects.length)
+					dstRects.push(lastRect);
+			}
+		}
+		
+		/** @private */
+		private function adjustEndElementForBidi(begIdx:int, endIdx:int, begElementIndex:int, direction:String):int
+		{
+			var endElementIndex:int = begElementIndex;
+			
+			var textLine:TextLine = getTextLine(true);
+			
+			if(endIdx != begIdx)
+			{
+				if(((direction == Direction.LTR && textLine.getAtomBidiLevel(begElementIndex)%2 != 0)
+					|| (direction == Direction.RTL && textLine.getAtomBidiLevel(begElementIndex)%2 == 0))
+					&& textLine.getAtomTextRotation(begElementIndex) != TextRotation.ROTATE_0)
+					endElementIndex = textLine.getAtomIndexAtCharIndex(endIdx);
+				else
+				{
+					endElementIndex = textLine.getAtomIndexAtCharIndex(endIdx - 1);
+				}
+			}
+			
+			if(endElementIndex == -1 && endIdx > 0)
+			{
+				return adjustEndElementForBidi(begIdx, endIdx - 1, begElementIndex, direction);
+			}
+			return endElementIndex;
+		}
+		
+		/** @private */
+		private function isAtomBidi(elementIdx:int, direction:String):Boolean
+		{
+			var textLine:TextLine = getTextLine(true);
+			
+			return (textLine.getAtomBidiLevel(elementIdx)%2 != 0 && direction == Direction.LTR) || (textLine.getAtomBidiLevel(elementIdx)%2 == 0 && direction == Direction.RTL);
+		}
+		
+		/** @private */
+		tlf_internal function get adornCount():int 
+		{ return _adornCount; }
+		
+		/** @private */
+		CONFIG::debug public function dumpToXML():String
+		{
+			var result:String = new String("<line");
+		
+			result = dumpAttribute(result, "absoluteStart", absoluteStart);
+			result = dumpAttribute(result, "textLength", textLength);
+			result = dumpAttribute(result, "height", height);
+			result = dumpAttribute(result, "spaceBefore", spaceBefore);
+
+			result = dumpAttribute(result, "spaceAfter", spaceAfter);
+			result = dumpAttribute(result, "location", location);
+			result = dumpAttribute(result, "x", x);
+			result = dumpAttribute(result, "y", y);
+			result = dumpAttribute(result, "targetWidth", targetWidth);
+			result = dumpAttribute(result, "lineOffset", _lineOffset);
+			result += ">\n";
+			
+			
+			var textLine:TextLine = getTextLine(true);
+			
+			result += "<TextBlock>";
+			result += textLine.textBlock.dump(); 
+			result += "</TextBlock>";
+			result += "<TextLine>"
+			result += textLine.dump();
+			result += "</TextLine>"
+			
+			result += "</line>";
+			return result;
+		}
+		
+	};
+}
+
+import flash.geom.Rectangle;
+
+import flashx.textLayout.edit.ISelectionManager;
+
+/** @private - I would have defined this as tlf_internal, but that is not an option, so
+ * making it private.
+ * 
+ * The SelectionCache is a structure designed to hold a few key data points needed to quickly
+ * reconstruct a selection on a line:
+ * 
+ * a) the beginning and end indicies of the selection on the line
+ * b) the regular selection rectangles
+ * c) the irregular selection rectangles, such as TCY selection rects in vertical text
+ * 
+ **/
+final class SelectionCache
+{
+	private var _begIdx:int = -1;
+	private var _endIdx:int = -1;
+	
+	private var _selectionBlocks:Array = null;
+	
+	public function SelectionCache()
+	{
+	}
+	
+	public function get begIdx():int 
+	{ return _begIdx; }
+	public function set begIdx(val:int):void	
+	{ _begIdx = val; }
+	
+	public function get endIdx():int 
+	{ return _endIdx; }
+	public function set endIdx(val:int):void	
+	{ _endIdx = val; }
+	
+	public function pushSelectionBlock(drawRect:Rectangle):void 
+	{
+		if(!_selectionBlocks)
+			_selectionBlocks = new Array();
+			
+		_selectionBlocks.push(drawRect.clone());
+	}
+	
+	public function get selectionBlocks():Array 
+	{ return _selectionBlocks; }
+	
+	
+	public function clear():void
+	{
+		_selectionBlocks = null;
+		_begIdx = -1;
+		_endIdx = -1;
+	}
+	
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/TextFlowLineLocation.as b/textLayout_core/src/flashx/textLayout/compose/TextFlowLineLocation.as
new file mode 100755
index 0000000..60e96e5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/TextFlowLineLocation.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 flashx.textLayout.compose
+{	
+	/** 
+	 * The TextFlowLineLocation class is an enumeration class that defines constants for specifying the location
+	 * of a line within a paragraph.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see ParagraphElement
+	 * @see TextFlow
+	 */
+	 
+	public final class TextFlowLineLocation
+	{ 
+		/** Specifies the first line in a paragraph. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const FIRST:uint = 1;
+		
+		/** Specifies a middle line in a paragraph - neither the first nor the last line. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const MIDDLE:uint = 2;
+		
+		/** Specifies the last line in a paragraph.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public static const LAST:uint = 4;
+		
+		/** Specifies both the first and last lines in a paragraph.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const ONLY:uint = 5;
+	};
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/TextLineRecycler.as b/textLayout_core/src/flashx/textLayout/compose/TextLineRecycler.as
new file mode 100755
index 0000000..2b9f118
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/TextLineRecycler.as
@@ -0,0 +1,129 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{	
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * The TextLineRecycler class provides support for recycling of TextLines.  Some player versions support a recreateTextLine.  Passing TextLines
+	 * to the recycler makes them available for reuse.  This improves Player performance.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */ 
+	public class TextLineRecycler
+	{
+		static private var _textLineRecyclerEnabled:Boolean = Configuration.playerEnablesArgoFeatures;
+		
+		/** Controls if the TLF recycler enabled.   It can only be enabled in 10.1 or later players.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function get textLineRecyclerEnabled():Boolean
+		{ return _textLineRecyclerEnabled; }
+		static public function set textLineRecyclerEnabled(value:Boolean):void
+		{ _textLineRecyclerEnabled = value ? Configuration.playerEnablesArgoFeatures : false; }
+		
+		// manage a cache of TextLine's that can be reused
+		// This version uses a dictionary that holds the TextLines as weak references
+		static private var reusableLineCache:Dictionary = new Dictionary(true);
+		
+		/**
+		 * Add a TextLine to the pool for reuse. TextLines for reuse should have null userData and null parent. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		static public function addLineForReuse(textLine:TextLine):void
+		{
+			CONFIG::debug { assert(textLine.parent == null && textLine.userData == null && (textLine.validity == TextLineValidity.INVALID || textLine.validity == TextLineValidity.STATIC),"textLine not ready for reuse"); }
+			if (_textLineRecyclerEnabled)
+			{
+				CONFIG::debug 
+				{
+					for each (var line:TextLine in reusableLineCache)
+					{
+						 assert(line != textLine,"READDING LINE TO CACHE");
+					}
+				}
+				CONFIG::debug { cacheTotal++; }
+				reusableLineCache[textLine] = null;
+			}
+		} 
+		CONFIG::debug
+		{
+			/** @private */
+			static tlf_internal var cacheTotal:int = 0;
+			/** @private */
+			static tlf_internal var fetchTotal:int = 0;
+			/** @private */
+			static tlf_internal var hitTotal:int = 0;		
+			
+			static private function recordFetch(hit:int):void
+			{
+				fetchTotal++;
+				hitTotal += hit;
+				
+				/*if ((fetchTotal%100) == 0)
+					trace(fetchTotal,hitTotal,cacheTotal);*/
+			}
+		}
+		
+		/**
+		 * Return a TextLine from the pool for reuse. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		static public function getLineForReuse():TextLine
+		{
+			if (_textLineRecyclerEnabled)
+			{
+				for (var obj:Object in reusableLineCache)
+				{
+					// remove from the cache
+					delete reusableLineCache[obj];
+					CONFIG::debug { assert(reusableLineCache[obj] === undefined,"Bad delete"); }
+					CONFIG::debug { recordFetch(1); }
+					return obj as TextLine;
+				}
+				CONFIG::debug { recordFetch(0); }
+			}
+			return null;
+		}
+		
+		/** @private empty the reusableLineCache */
+		static tlf_internal function emptyReusableLineCache():void
+		{
+			reusableLineCache = new Dictionary(true);
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/compose/VerticalJustifier.as b/textLayout_core/src/flashx/textLayout/compose/VerticalJustifier.as
new file mode 100755
index 0000000..7b59ee6
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/compose/VerticalJustifier.as
@@ -0,0 +1,303 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.VerticalAlign;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** @private
+	 * Adjust line positions according to verticalAlign settings.  Vertical alignment is perpendicular
+	 * to the linebreak direction.
+	 */
+	public final class VerticalJustifier
+	{
+		[ ArrayElementType("text.IVerticalJustificationLine") ] 
+		/** Vertical justify the subset of lines from startIndext to startIndex to numLines according to the rule specified by verticalAlignAttr.  
+		 * The assumption is that they are all the lines in a single column of cont. 
+		 * @see text.formats.VerticalAlign
+		 * */
+		static public function applyVerticalAlignmentToColumn(cont:ContainerController, verticalAlignAttr:String, lines:Array, startIndex:int, numLines:int):void
+		{
+			// TODO: This function doesn't work if there are any tables.
+			
+			var helper:IVerticalAdjustmentHelper;
+			if (cont.rootElement.computedFormat.blockProgression == BlockProgression.RL)
+				helper = new RL_VJHelper(ContainerController(cont));
+			else
+				helper = new TB_VJHelper(ContainerController(cont));
+				
+			CONFIG::debug { assert(startIndex + numLines <= lines.length && numLines > 0,"applyVerticalAlignmentToColumn: bad indices"); }
+									
+			var i:int;
+			
+			switch(verticalAlignAttr) 
+			{
+				case VerticalAlign.MIDDLE:
+					helper.computeMiddleAdjustment(lines[(startIndex + numLines) - 1]);
+					for (i = startIndex; i < startIndex + numLines; i++)
+						helper.applyMiddleAdjustment(lines[i]);
+					break;
+				case VerticalAlign.BOTTOM:
+					helper.computeBottomAdjustment(lines[(startIndex + numLines) - 1]);
+					for (i = startIndex; i < startIndex + numLines; i++)
+						helper.applyBottomAdjustment(lines[i]);
+					break;
+				case VerticalAlign.JUSTIFY:
+					helper.computeJustifyAdjustment(lines, startIndex, numLines);
+					helper.applyJustifyAdjustment(lines, startIndex, numLines);
+					break;
+			}
+
+			//for (i = startIndex; i < startIndex + numLines; i++)
+			//	trace("x=", sc[i].x, "y=", sc[i].y, "yAdj=", yAdj);
+		}
+	}
+}
+import flash.text.engine.TextLine;
+import flashx.textLayout.compose.IVerticalJustificationLine;
+import flashx.textLayout.container.ContainerController;
+import flashx.textLayout.compose.TextFlowLine;
+import flashx.textLayout.compose.TextFlowLine;
+
+
+interface IVerticalAdjustmentHelper
+{
+	function computeMiddleAdjustment(lastLine:IVerticalJustificationLine):void;
+	function applyMiddleAdjustment(line:IVerticalJustificationLine):void;
+	
+	function computeBottomAdjustment(lastLine:IVerticalJustificationLine):void;
+	function applyBottomAdjustment(line:IVerticalJustificationLine):void;
+	
+	function computeJustifyAdjustment(lineArray:Array, firstLine:int, numLines:int):void;
+	function applyJustifyAdjustment(lineArray:Array, firstLine:int, numLines:int):void;
+}
+
+class TB_VJHelper implements IVerticalAdjustmentHelper
+{
+	import flashx.textLayout.tlf_internal;	
+	use namespace tlf_internal;
+	
+	private var _textFrame:ContainerController;
+	private var adj:Number;
+	
+	public function TB_VJHelper(tf:ContainerController):void
+	{
+		_textFrame = tf;
+	}
+	
+	private function getBottomOfLine(line:IVerticalJustificationLine):Number
+	{
+		return getBaseline(line) + line.descent;
+	}
+	
+	private function getBaseline(line:IVerticalJustificationLine):Number
+	{
+		if (line is TextFlowLine)
+			return line.y + line.ascent;
+		else
+			return line.y;
+	}
+	
+	private function setBaseline(line:IVerticalJustificationLine, pos:Number):void
+	{
+		if (line is TextFlowLine)
+			line.y = pos - line.ascent;
+		else
+			line.y = pos;
+	}
+	
+	// half of the available adjustment added to each y to shift the lines half way down the frame
+	public function computeMiddleAdjustment(lastLine:IVerticalJustificationLine):void
+	{
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.effectivePaddingBottom);
+		adj = (frameBottom - getBottomOfLine(lastLine)) / 2;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+	}
+	public function applyMiddleAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.y = line.y + adj;
+	}
+	
+	// the baseline of the last line should be at the bottom of the frame - paddingBottom.
+	public function computeBottomAdjustment(lastLine:IVerticalJustificationLine):void
+	{
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.effectivePaddingBottom);
+		adj = frameBottom - getBottomOfLine(lastLine);
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+	}
+	public function applyBottomAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.y = line.y + adj;
+	}
+	
+	// one line: untouched, two lines: first line untouched and descent of last line at the bottom of the frame, 
+	// and more than two lines: line spacing increased proportionally, with first line untouched and descent of last line at the bottom of the frame
+	[ ArrayElementType("text.compose.IVerticalJustificationLine") ]
+	public function computeJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{
+		adj = 0;
+		
+		if (numLines == 1)
+			return;	// do nothing
+			
+		// first line unchanged	
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var firstBaseLine:Number =  getBaseline(firstLine);
+
+		// descent of the last line on the bottom of the frame	
+		var lastLine:IVerticalJustificationLine = lineArray[firstLineIndex + numLines - 1];
+		var frameBottom:Number = _textFrame.compositionHeight - Number(_textFrame.effectivePaddingBottom);
+		var allowance:Number = frameBottom - getBottomOfLine(lastLine);
+		if (allowance < 0)
+			return; // Some text scrolled out; don't justify
+		var lastBaseLine:Number = getBaseline(lastLine); 
+	
+		adj = allowance/(lastBaseLine - firstBaseLine); // multiplicative factor by which the space between consecutive lines is increased 
+	}
+	
+	[ ArrayElementType("text.compose.IVerticalJustificationLine") ]
+	public function applyJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{ 
+		if (numLines == 1 || adj == 0)
+			return;	// do nothing
+			
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var prevBaseLine:Number = getBaseline(firstLine);
+		var prevBaseLineUnjustified:Number = prevBaseLine;
+		
+		var line:IVerticalJustificationLine;
+		var currBaseLine:Number;
+		var currBaseLineUnjustified:Number;
+		
+		for (var i:int = 1; i < numLines; i++)
+		{
+			line = lineArray[i + firstLineIndex];
+			currBaseLineUnjustified = getBaseline(line);
+			
+			// Space between consecutive baselines scaled up by the calculated factor
+			currBaseLine = prevBaseLine  + (currBaseLineUnjustified - prevBaseLineUnjustified)*(1 + adj);
+			setBaseline(line, currBaseLine);
+			
+			prevBaseLineUnjustified = currBaseLineUnjustified;
+			prevBaseLine = currBaseLine;
+		}
+	}
+}
+
+class RL_VJHelper implements IVerticalAdjustmentHelper
+{
+	import flashx.textLayout.tlf_internal;	
+	use namespace tlf_internal;
+
+	private var _textFrame:ContainerController;
+	private var adj:Number = 0;
+	
+	public function RL_VJHelper(tf:ContainerController):void
+	{
+		_textFrame = tf;
+	}
+	
+	// half of the available adjustment added to each x to shift the lines half way left across the frame
+	public function computeMiddleAdjustment(lastTextLine:IVerticalJustificationLine):void
+	{
+		// ignore paddingRight its already offset
+		var frameWidth:Number = _textFrame.compositionWidth-Number(_textFrame.effectivePaddingLeft);
+		adj = (frameWidth + lastTextLine.x - lastTextLine.descent) / 2;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+	}
+	public function applyMiddleAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.x = (line.x - adj);
+	}
+	
+	// the baseline of the last line should be at the bottom of the frame - paddingLeft.
+	public function computeBottomAdjustment(lastTextLine:IVerticalJustificationLine):void
+	{
+		var frameWidth:Number = _textFrame.compositionWidth-Number(_textFrame.effectivePaddingLeft);
+		adj = frameWidth + lastTextLine.x - lastTextLine.descent;
+		if (adj < 0)
+			adj = 0; // no space available to redistribute
+	}
+	public function applyBottomAdjustment(line:IVerticalJustificationLine):void
+	{
+		line.x = (line.x - adj);
+	}
+	
+	// one line: untouched, two lines: first line untouched and descent of last line at the bottom of the frame, 
+	// and more than two lines: line spacing increased proportionally, with first line untouched and descent of last line at the bottom of the frame
+	[ ArrayElementType("text.compose.IVerticalJustificationLine") ]
+	public function computeJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{ 
+		adj = 0;
+		
+		if (numLines == 1)
+			return;	// do nothing
+			
+		// first line unchanged
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var firstBaseLine:Number =  firstLine.x;
+		
+		// descent of the last line on the left of the frame	
+		var lastLine:IVerticalJustificationLine = lineArray[firstLineIndex + numLines - 1];
+		var frameLeft:Number =  Number(_textFrame.effectivePaddingLeft) - _textFrame.compositionWidth;
+		var allowance:Number = (lastLine.x - lastLine.descent) - frameLeft;
+		if (allowance < 0)
+			return; // Some text scrolled out; don't justify
+		var lastBaseLine:Number = lastLine.x;  
+		
+		adj = allowance/(firstBaseLine - lastBaseLine);  // multiplicative factor by which the space between consecutive lines is increased 
+	}
+	
+	[ ArrayElementType("text.IVerticalJustificationLine") ]
+	public function applyJustifyAdjustment(lineArray:Array, firstLineIndex:int, numLines:int):void
+	{
+		if (numLines == 1 || adj == 0)
+			return;	// do nothing
+			
+		var firstLine:IVerticalJustificationLine = lineArray[firstLineIndex];
+		var prevBaseLine:Number = firstLine.x;
+		var prevBaseLineUnjustified:Number = prevBaseLine;
+		
+		var line:IVerticalJustificationLine;
+		var currBaseLine:Number;
+		var currBaseLineUnjustified:Number;
+		
+		for (var i:int = 1; i < numLines; i++)
+		{
+			line = lineArray[i + firstLineIndex];
+			currBaseLineUnjustified = line.x;
+			
+			// Space between consecutive baselines scaled up by the calculated factor
+			currBaseLine = prevBaseLine - (prevBaseLineUnjustified - currBaseLineUnjustified)*(1 + adj);
+			line.x = currBaseLine;
+			
+			prevBaseLineUnjustified = currBaseLineUnjustified;
+			prevBaseLine = currBaseLine;
+		}		
+	}
+	
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/container/ColumnState.as b/textLayout_core/src/flashx/textLayout/container/ColumnState.as
new file mode 100755
index 0000000..6e982ef
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/container/ColumnState.as
@@ -0,0 +1,392 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+	import flash.geom.Rectangle;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+
+	/** 
+	 * The ColumnState class calculates the sizes and locations of columns using
+	 * the width of the container and the container attributes. You can create instances of this class 
+	 * independently to calculate column values, or you can get the column values that 
+	 * were used for the text after the container has been composed or updated (redrawn).
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see ContainerController
+	 */
+
+	public class ColumnState 
+	{
+		// input information
+		private var _inputsChanged:Boolean;
+		private var _blockProgression:String;
+		private var _columnDirection:String;
+		private var _paddingTop:Number;
+		private var _paddingBottom:Number;
+		private var _paddingLeft:Number;
+		private var _paddingRight:Number;
+		private var _compositionWidth:Number;
+		private var _compositionHeight:Number;
+		private var _forceSingleColumn:Boolean;
+		
+		private var _inputColumnWidth:Object;
+		private var _inputColumnGap:Number;
+		private var _inputColumnCount:Object
+		
+		// Generated column information		
+		private var _columnWidth:Number;	
+		private var _columnCount:int;		
+		private var _columnGap:Number;	
+		private var _inset:Number;
+		
+		// and the array of columns
+		private var _columnArray:Array;
+		private var _singleColumn:Rectangle;
+		
+		/**
+		 * Constructor function - creates a ColumnState object.
+		 *
+		 * If the values of <code>controller.compositionWidth</code> and <code>controller.compositionHeight</code> equal
+		 * <code>NaN</code> (not a number), the constructor measures the container's contents to determine the actual 
+		 * composition width and height that feed into ColumnState.
+		 *
+		 * Use the constants defined by the <code>flashx.textLayout.formats.BlockProgression</code> class to 
+		 * specify the value of the <code>blockProgression</code> parameter. Use the constants defined by
+		 * <code>flashx.textLayout.formats.Direction</code> to specify the value of the <code>columnDirection</code> 
+		 * parameter.
+		 *
+		 * @param blockProgression The direction of lines for the textflow, either BlockProgression.TB (top-to-bottom) or 
+		 * 		BlockProgression.RL (right-to-left).
+		 * @param columnDirection The direction of column layout for the text flow, either Direction.RTL (right-to-left) or 
+		 * 		Direction.LTR (left-to-right).
+		 * @param controller A ContainerController instance whose attributes are used to calculate the column values.
+		 * @param compositionWidth The horizontal extent, in pixels, allowed for text inside the container.
+		 * @param compositionHeight The vertical extent, in pixels, allowed for text inside the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.formats.BlockProgression BlockProgression
+		 * @see flashx.textLayout.formats.Direction Direction
+	 	 */
+		
+		public function ColumnState(blockProgression:String, columnDirection:String, controller:ContainerController, compositionWidth:Number, compositionHeight:Number)
+		{
+			_inputsChanged = true;
+			_columnCount = 0;
+
+			if (blockProgression != null)		// if values are legit, recalculate now. They might not be, if this is called from a containerController constructor.
+			{		
+				updateInputs(blockProgression, columnDirection, controller, compositionWidth, compositionHeight);
+				computeColumns();
+			}
+		}
+		
+		/** 
+		 * The width of columns, in pixels, in the container. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get columnWidth():Number
+		{ return _columnWidth; }
+
+		/** 
+		 * The number of columns in the container. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get columnCount():int
+		{ return _columnCount; }
+
+		/** 
+		 * The amount of space, in pixels, left between columns in the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get columnGap():Number
+		{ return _columnGap; }
+		
+		/** 
+		 * Returns the area that a column takes within the container. Allows you to access the area for a 
+		 * specific column.
+		 *
+		 * @param index The relative position of the column among all columns in the container, with the first
+		 * 	column at position 0.
+		 *
+		 * @return The area of the specified column.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public function getColumnAt(index:int):Rectangle
+		{
+			return _columnCount == 1 ? _singleColumn : _columnArray[index];
+		}
+
+		/** Recalculate actual column settings based on attributes and width
+		 * from the container. Call this after either the attributes or the
+		 * width has been changed to get the new values.
+		 *
+		 * @param newBlockProgression block progression for the textflow
+		 * @param newColumnDirection column layout direction for the textflow
+		 * @param containerAttr		Formatting attributes from the container
+		 * @param containerWidth		Width of the container
+		 * @return Boolean			true if the actual column settings have changed
+		 * @private 
+		 */
+		tlf_internal function updateInputs(newBlockProgression:String, newColumnDirection:String, controller:ContainerController, newCompositionWidth:Number, newCompositionHeight:Number ):void
+		{
+			var newPaddingTop:Number = controller.effectivePaddingTop;
+			var newPaddingBottom:Number = controller.effectivePaddingBottom;
+			var newPaddingLeft:Number = controller.effectivePaddingLeft;
+			var newPaddingRight:Number = controller.effectivePaddingRight;
+			
+			var containerAttr:ITextLayoutFormat = controller.computedFormat;
+			
+			var newColumnWidth:Object = containerAttr.columnWidth;
+			var newColumnGap:Number = containerAttr.columnGap;
+			var newColumnCount:Object = containerAttr.columnCount;;
+			
+			var newForceSingleColumn:Boolean = ((containerAttr.columnCount == FormatValue.AUTO && (containerAttr.columnWidth == FormatValue.AUTO || Number(containerAttr.columnWidth) == 0)) ||
+				controller.rootElement.computedFormat.lineBreak == LineBreak.EXPLICIT)
+			
+			if (_inputsChanged == false) 
+				_inputsChanged = newCompositionWidth != _compositionHeight || newCompositionHeight != _compositionHeight
+				|| _paddingTop != newPaddingTop || _paddingBottom != newPaddingBottom || _paddingLeft != newPaddingLeft || _paddingRight != newPaddingRight
+				|| _blockProgression != _blockProgression || _columnDirection != newColumnDirection || _forceSingleColumn != newForceSingleColumn
+				|| _inputColumnWidth != newColumnWidth || _inputColumnGap != newColumnGap || _inputColumnCount != newColumnCount;
+				
+			if (_inputsChanged)
+			{
+				_blockProgression = newBlockProgression;
+				_columnDirection = newColumnDirection;
+				_paddingTop = newPaddingTop;
+				_paddingBottom = newPaddingBottom;
+				_paddingLeft = newPaddingLeft;
+				_paddingRight = newPaddingRight;
+				_compositionWidth = newCompositionWidth;
+				_compositionHeight = newCompositionHeight;
+				_forceSingleColumn = newForceSingleColumn;
+				
+				_inputColumnWidth = newColumnWidth;
+				_inputColumnGap = newColumnGap;
+				_inputColumnCount = newColumnCount;
+			}
+		}
+
+		/** Compute the actual columns based on the input values @private */
+		tlf_internal function computeColumns():void
+		{
+			if (!_inputsChanged)
+				return;
+				
+			// Recalculate all the column settings. Returns true if settings have changed as a result.
+			// See http://www.w3.org/TR/2005/WD-css3-multicol-20051215/#the-number
+			var newColumnGap:Number;
+			var newColumnCount:int;
+			var newColumnWidth:Number;
+			
+			// calculate the width to divy the columns up among
+			var totalColumnWidth:Number = _blockProgression == BlockProgression.RL ? _compositionHeight : _compositionWidth;
+			// inset to use
+			var newColumnInset:Number   = _blockProgression == BlockProgression.RL ? _paddingTop + _paddingBottom : _paddingLeft + _paddingRight;
+				
+			totalColumnWidth = (totalColumnWidth > newColumnInset && !isNaN(totalColumnWidth)) ? totalColumnWidth - newColumnInset : 0;
+			
+			// columnCount is auto && columnWidth is auto || 0 --> one column
+			if (_forceSingleColumn)
+			{
+				// This case deviates from the spec.  Spec is no columns.  
+				// TextLayout does either one auto full width column or a zero width column
+				newColumnCount = 1;
+				newColumnWidth = totalColumnWidth; 
+				newColumnGap = 0;
+			}
+			else
+			{
+				newColumnGap   = _inputColumnGap;
+				
+				if (_inputColumnWidth == FormatValue.AUTO)		// auto
+				{
+					newColumnCount = Number(_inputColumnCount);
+					// Column width is not specified, we'll use columnCount and columnGap to figure it out
+					if ((newColumnCount-1)*newColumnGap < totalColumnWidth)
+					{
+						newColumnWidth = (totalColumnWidth - (newColumnCount-1)*newColumnGap) / newColumnCount;
+					}
+					else if (newColumnGap > totalColumnWidth)
+					{
+						newColumnCount = 1;
+						newColumnWidth = totalColumnWidth;
+						newColumnGap = 0;
+					}
+					else
+					{
+						newColumnCount = Math.floor(totalColumnWidth/newColumnGap);
+						newColumnWidth = (totalColumnWidth-(newColumnCount-1)*newColumnGap)/newColumnCount;
+						// newColumnGap = newColumnCount == 1 ? 0 : (totalColumnWidth - newColumnWidth*newColumnCount) / (newColumnCount-1);
+					}
+				}
+				else if (_inputColumnCount == FormatValue.AUTO)	// auto
+				{
+					newColumnWidth = Number(_inputColumnWidth);
+					if (newColumnWidth >= totalColumnWidth)
+					{
+						newColumnCount = 1;
+						newColumnWidth = totalColumnWidth;
+						newColumnGap   = 0;
+					}
+					else
+					{
+						newColumnCount = Math.floor((totalColumnWidth+newColumnGap)/(newColumnWidth+newColumnGap));
+						newColumnWidth = ((totalColumnWidth+newColumnGap)/newColumnCount) - newColumnGap;
+					}
+				}
+				else
+				{
+					newColumnCount = Number(_inputColumnCount);
+					newColumnWidth = Number(_inputColumnWidth);
+					if (newColumnCount*newColumnWidth+(newColumnCount-1)*newColumnGap <= totalColumnWidth)
+					{
+						// done
+					}
+					else if (newColumnWidth >= totalColumnWidth)
+					{
+						newColumnCount = 1;
+						newColumnGap = 0;
+						// use newColumnWidth
+					}
+					else
+					{
+						newColumnCount = Math.floor( (totalColumnWidth+newColumnGap) / (newColumnWidth+newColumnGap) );
+						newColumnWidth = ((totalColumnWidth+newColumnGap) / newColumnCount) - newColumnGap;
+					}
+				}
+			}
+				
+			_columnWidth = newColumnWidth;
+			_columnCount = newColumnCount;
+			_columnGap = newColumnGap;
+			_inset = newColumnInset;			
+	
+			// setup these values for each case
+			var xPos:Number;
+			var yPos:Number;
+			var delX:Number;
+			var delY:Number;
+			var colH:Number;
+			var colW:Number;
+			
+			// scratch vars
+			var insetHeight:Number;
+			
+			// TODO: USE DIRECTION!!!
+			if (_blockProgression == BlockProgression.TB)
+			{
+				if (_columnDirection == Direction.LTR)
+				{
+					xPos = _paddingLeft;
+					delX = _columnWidth + _columnGap;
+					colW = _columnWidth;
+				}
+				else
+				{
+					CONFIG::debug { assert(_columnDirection == Direction.RTL,"bad columndirection in ColumnState.computeColumns"); }
+					xPos = isNaN(_compositionWidth) ? 0 : _compositionWidth-_paddingRight-_columnWidth;
+					delX = -(_columnWidth + _columnGap);
+					colW = _columnWidth;
+				}
+				yPos = _paddingTop;
+				delY = 0;
+				insetHeight = _paddingTop + _paddingBottom;
+				colH = (_compositionHeight > insetHeight && !isNaN(_compositionHeight)) ? (_compositionHeight - insetHeight) : 0;
+			}
+			else if (_blockProgression == BlockProgression.RL)
+			{
+				xPos = isNaN(_compositionWidth) ? -_paddingRight : _paddingLeft -_compositionWidth;
+				yPos = _paddingTop;
+				delX = 0;
+				delY = _columnWidth + _columnGap;
+				insetHeight = _paddingLeft + _paddingRight;
+				colW = (_compositionWidth > insetHeight) ? (_compositionWidth - insetHeight) : 0;
+				colH = _columnWidth;
+			}
+			
+			// make colW and colH just off zero so that we don't get empties
+			if (colW == 0)
+			{
+				colW = .001;
+				if (_blockProgression == BlockProgression.RL)
+					xPos -= colW;
+			}
+			if (colH == 0)
+				colH = .001;
+			
+			if (_columnCount == 1)
+			{
+				_singleColumn = new Rectangle(xPos, yPos, colW, colH);
+				_columnArray = null;
+			}
+			else if (_columnCount == 0)
+			{
+				_singleColumn = null;
+				_columnArray = null;
+			}
+			else
+			{
+				if (_columnArray)
+					_columnArray.splice(0);
+				else
+					_columnArray = new Array();
+				for (var i:int = 0; i < _columnCount; ++i)
+				{
+					_columnArray.push(new Rectangle(xPos, yPos, colW, colH));
+					xPos += delX;
+					yPos += delY;
+				}
+			}	
+		}
+	}
+		
+
+} // end package
diff --git a/textLayout_core/src/flashx/textLayout/container/ContainerController.as b/textLayout_core/src/flashx/textLayout/container/ContainerController.as
new file mode 100755
index 0000000..b3a34b5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/container/ContainerController.as
@@ -0,0 +1,3389 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container 
+{
+	import flash.display.BlendMode;
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.display.InteractiveObject;
+	import flash.display.Shape;
+	import flash.display.Sprite;
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.IMEEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.TextEvent;
+	import flash.events.TimerEvent;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.ui.ContextMenu;
+	import flash.ui.ContextMenuClipboardItems;
+	import flash.utils.Timer;
+	
+	import flashx.textLayout.compose.FlowDamageType;
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextLineRecycler;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.EditingMode;
+	import flashx.textLayout.edit.IInteractionEventHandler;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.edit.SelectionFormat;
+	import flashx.textLayout.elements.BackgroundManager;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.FlowValueHolder;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.TextLayoutEvent;
+	import flashx.textLayout.events.UpdateCompleteEvent;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+		
+	/** 
+	 * The  ContainerController class defines the relationship between a TextFlow object and a container.
+	 * A TextFlow may have one or more rectangular areas that can hold text; the text is said to be flowing
+	 * through the containers. Each container is a Sprite that is the parent DisplayObject for the TextLines.
+	 * Each container has a ContainerController that manages the container; the controller holds the target 
+	 * width and height for the text area, populates the container with TextLines, and handles scrolling. A
+	 * controller also has a format associated with it that allows some formatting attributes to be applied 
+	 * to the text in the container. This allows, for instance, a TextFlow to have one container where the
+	 * text appears in a single column, and a second container in the same TextFlow with two column text. Not
+	 * all formatting attributes that can be applied to the container will affect the text; only the ones that
+	 * affect container-level layout. The diagram below illustrates the relationship between the TextFlow,
+	 * its flowComposer, and the display list.
+	 *
+	 * <p><img src="../../../images/textLayout_multiController.gif" alt="IContainerController"></img></p>
+	 *
+	 * @includeExample examples\ContainerControllerExample1.as -noswf
+	 * @includeExample examples\ContainerControllerExample2.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see flashx.textLayout.compose.IFlowComposer
+	 * @see flashx.textLayout.elements.TextFlow
+	 * @see flashx.textLayout.container.TextContainerController
+	 */
+	public class ContainerController implements IInteractionEventHandler, ITextLayoutFormat, ISandboxSupport
+	{		
+		private var _textFlowCache:TextFlow;
+		private var _rootElement:ContainerFormattedElement;
+		
+		private var _absoluteStart:int;
+		private var _textLength:int;
+		
+		private var _container:Sprite;
+		
+		// note must be protected - subclass sets or gets this variable but can't be public
+		/** computed container attributes.  @private */
+		protected var _computedFormat:ITextLayoutFormat;
+		
+		// Generated column information
+		// Generated column information
+		private var _columnState:ColumnState;
+		
+		/** Container size to be composed */
+		private var _compositionWidth:Number = 0;
+		private var _compositionHeight:Number = 0;
+		private var _measureWidth:Boolean; // true if we're measuring (isNaN(compositionWidth) optimization so we don't call isNaN too much
+		private var _measureHeight:Boolean; // true if we're measuring (isNaN(compositionHeight) optimization so we don't call isNaN too much
+		
+		/* Text bounds after composition */
+		private var _contentLeft:Number;
+		private var _contentTop:Number;
+		private var _contentWidth:Number;
+		private var _contentHeight:Number;
+		
+		private var _composeCompleteRatio:Number;	// 1 if composition was complete when contentHeight, etc registered, greater than one otherwise
+
+		// Scroll policy -- determines whether scrolling is enabled or not
+		private var _horizontalScrollPolicy:String;
+		private var _verticalScrollPolicy:String;
+		
+		// x, y location of the text in the container relative to the underlying scrollable area
+		private var _xScroll:Number;
+		private var _yScroll:Number;
+		
+		/** Are event listeners attached to the container */
+		private var _minListenersAttached:Boolean = false;
+		private var _allListenersAttached:Boolean = false;
+		private var _selectListenersAttached:Boolean = false;
+		
+		/** @private */
+		tlf_internal function get allListenersAttached():Boolean
+		{ return _allListenersAttached; }
+	
+		/** Are the displayed shapes out of date? */
+		private var _shapesInvalid:Boolean = false;
+
+		private var _backgroundShape:Shape;
+		
+		private var _scrollTimer:Timer = null;
+		
+		/**
+		 * @private use this boolean to determine if container.scrollRect is set.  Accessing scrollRect when null changes the rendering behavior of flash player.	
+		*/
+		protected var _hasScrollRect:Boolean;
+		
+		/** 
+		 * @private
+		 * 
+		 * <p>This property enables a client to test for a ScrollRect object without accessing 
+		 * the DisplayObject.scrollRect property, which can have side effects in some cases.</p> 
+		 *
+		 * @return true if the controller has attached a ScrollRect instance.
+		 */
+		tlf_internal function get hasScrollRect():Boolean
+		{ return _hasScrollRect; }
+		
+		CONFIG::debug
+		{
+			protected var id:String;
+			private static var contCount:int = 0;
+		}
+		
+		private var _shapeChildren:Array;
+
+		private var _formatValueHolder:FlowValueHolder;
+		
+		private var _containerRoot:DisplayObject;
+		
+		/* Controller have a non-zero default width and height so that if you construct a text example with a container and don't
+		 * specify width and height you will still see some text so that you can then have a clue what to do to correct its appearance.
+		 */
+		 
+		/** 
+		 * Constructor - creates a ContainerController instance. The ContainerController has a default <code>compositionWidth</code>
+		 * and <code>compositionHeight</code> so that some text appears in the container if you don't specify its width
+		 * height.
+		 *
+		 * @param container The DisplayObjectContainer in which to manage the text lines.
+		 * @param compositionWidth The initial width for composing text in the container.
+		 * @param compositionHeight The initial height for composing text in the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public function ContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100)
+		{
+			initialize(container,compositionWidth,compositionHeight);
+		}
+		
+		private function initialize(container:Sprite,compositionWidth:Number,compositionHeight:Number):void
+		{
+			_container = container;
+			_containerRoot =  null;
+			
+			_textLength = 0;
+			_absoluteStart = -1;
+		
+			_columnState = new ColumnState(null/*blockProgression*/, null/*columnDirection*/, null/*controller*/, 0/*compositionWidth*/, 0/*compositionHeight*/);
+			//_visibleRect = new Rectangle();
+			_xScroll = _yScroll = 0;
+			_contentWidth = _contentHeight = 0;
+			_composeCompleteRatio = 1;
+
+			// We have to set the flag so that we will get double click events. This
+			// is a change to the container we are given, but a minor one.
+			if (_container is InteractiveObject)
+				InteractiveObject(_container).doubleClickEnabled = true;
+
+			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);
+			_hasScrollRect = false;
+
+			CONFIG::debug { id = contCount.toString(); ++contCount; }
+
+			_shapeChildren = [ ];
+			
+			setCompositionSize(compositionWidth, compositionHeight);
+			format = _containerControllerInitialFormat;
+		}
+
+		/** @private */
+		tlf_internal function get effectiveBlockProgression():String
+		{
+			return _rootElement ? _rootElement.computedFormat.blockProgression : BlockProgression.TB;
+		}
+		
+		/** @private  Determine containerRoot in case the stage is not accessible. Normally the root is the stage. */
+		tlf_internal function getContainerRoot():DisplayObject
+		{
+			// safe to test for stage existence
+			if (_containerRoot == null && _container && _container.stage)
+			{
+				// if the stage is accessible lets use it.
+				// trace("BEFORE COMPUTING CONTAINERROOT");
+				try
+				{
+					var x:int = _container.stage.numChildren;
+					_containerRoot = _container.stage;
+				}
+				catch(e:Error)
+				{
+					// TODO: some way to find the highest level accessible root???
+					_containerRoot = _container.root;
+				}
+				// trace("AFTER COMPUTING CONTAINERROOT");
+			}
+			return _containerRoot;
+		}
+		
+		/** 
+		 * Returns the flow composer object that composes and highlights text into the container that this 
+		 * controller manages. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.compose.IFlowComposer
+	 	 */
+
+		public function get flowComposer():IFlowComposer
+		{ return textFlow ? textFlow.flowComposer : null; }
+		
+		/** @private */
+		tlf_internal function get shapesInvalid():Boolean
+		{ return _shapesInvalid; }
+		/** @private */
+		tlf_internal function set shapesInvalid(val:Boolean):void
+		{ _shapesInvalid = val;	}
+		
+		/** 
+		 * Returns a ColumnState object, which describes the number and characteristics of columns in
+		 * the container. These values are updated when the text is recomposed, either as a result
+		 * of <code>IFlowComposer.compose()</code> or <code>IFlowComposer.updateAllControllers()</code>.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see ColumnState
+	 	 */
+		 
+		public function get columnState():ColumnState
+		{
+			if (_rootElement == null)
+				return null;
+			
+			if (_computedFormat == null)
+				computedFormat;
+				
+			_columnState.computeColumns();
+
+			return _columnState; 
+		}
+		
+		/** 
+		 * Returns the container display object that holds the text lines for this ContainerController instance. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #ContainerController()
+	 	 */
+	 	 		 
+		public function get container():Sprite
+		{ return _container; }
+		
+		/** 
+		 * Returns the horizontal extent allowed for text inside the container. The value is specified in pixels.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #setCompositionSize()
+		 */
+		 
+		public function get compositionWidth():Number
+		{ return _compositionWidth; }
+		
+		/** 
+		 * Returns the vertical extent allowed for text inside the container. The value is specified in pixels.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #setCompositionSize()
+	 	 */
+ 		 
+		public function get compositionHeight():Number
+		{ return _compositionHeight; }
+		
+		/** @private */
+		tlf_internal function get measureWidth():Boolean
+		{ return _measureWidth; }
+				
+		/** @private */
+		tlf_internal function get measureHeight():Boolean
+		{ return _measureHeight; }
+			
+		/** 
+		 * Sets the width and height allowed for text in the container. 
+		 *
+		 * @param w The width in pixels that's available for text in the container.
+		 * @param h The height in pixels that's available for text in the container.
+		 *
+		 * @includeExample examples\ContainerController_setCompositionSizeExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		
+		public function setCompositionSize(w:Number,h:Number):void
+		{
+			// note: NaN == NaN is always false
+			var widthChanged:Boolean  =  !(_compositionWidth == w || (isNaN(_compositionWidth) && isNaN(w)));
+			var heightChanged:Boolean =  !(_compositionHeight == h || (isNaN(_compositionHeight) && isNaN(h)));
+			
+			if (widthChanged || heightChanged)
+			{
+				_compositionHeight = h;
+				_measureHeight = isNaN(_compositionHeight);
+				_compositionWidth = w;
+				_measureWidth = isNaN(_compositionWidth);
+				// otherwise the reset will happen when the cascade is done
+				if (_computedFormat)
+					resetColumnState();
+				invalidateContents();
+				attachTransparentBackgroundForHit(false);
+			}
+		}
+		
+		/** 
+		 * Returns the TextFlow object whose content appears in the container. Either the <code>textFlow</code> and  
+		 * <code>rootElement</code> values are the same, or this is the root element's TextFlow object. For example,
+		 * if the container's root element is a DivElement, the value would be the TextFlow object to which the
+		 * DivElement belongs.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.elements.TextFlow TextFlow
+	 	 */
+		 
+		public function get textFlow():TextFlow
+		{ 
+			if (!_textFlowCache && _rootElement)
+				_textFlowCache = _rootElement.getTextFlow();
+			return _textFlowCache;
+		}
+		
+		 // Reserve possibility for future use as a ContainerFormattedElement within the TextFlow.
+		 
+		/** 
+		 * Returns the root element that appears in the container. The root element could be a DivElement or TextFlow
+		 * instance, for example.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.elements.ContainerFormattedElement
+	 	 * @see flashx.textLayout.elements.DivElement
+	 	 * @see flashx.textLayout.elements.TextFlow
+	 	 */
+		 
+		public function get rootElement():ContainerFormattedElement
+		{ return _rootElement; }
+		
+		/** Protected method used when updating the rootElement. 
+		 * @param value new container to be controlled
+		 * 
+		 * @private
+		 */
+		tlf_internal function setRootElement(value:ContainerFormattedElement):void
+		{
+			if (_rootElement != value)
+			{
+				clearCompositionResults();
+				detachContainer();
+				_rootElement = value;
+				_textFlowCache = null;
+				_textLength = 0;
+				_absoluteStart = -1;
+				attachContainer();
+				if (_rootElement)
+					formatChanged();
+			}
+		}
+
+		/** 
+		 * @copy flashx.textLayout.elements.TextFlow#interactionManager
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.elements.TextFlow#interactionManager
+		 */
+		 
+		public function get interactionManager():ISelectionManager
+		{
+			return textFlow ? textFlow.interactionManager : null;
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Start and length
+		//
+		//--------------------------------------------------------------------------
+		
+		/** 
+		 * Returns the first character in the container. If this is not the first container in the flow,
+		 * this value is updated when the text is composed, that is when the IFlowComposer's <code>compose()</code> or 
+ 		 * <code>updateAllControllers()</code> methods are called.
+		 * 
+	 	 * @see flashx.textLayout.compose.IFlowComposer
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		public function get absoluteStart():int
+		{
+			if (_absoluteStart != -1)
+				return _absoluteStart;
+				
+			var rslt:int = 0;
+			var composer:IFlowComposer = flowComposer;
+			if (composer)
+			{
+				var stopIdx:int = composer.getControllerIndex(this);
+				if (stopIdx != 0)
+				{
+					var prevController:ContainerController = composer.getControllerAt(stopIdx-1);
+					rslt = prevController.absoluteStart + prevController.textLength;
+				}
+			}
+			_absoluteStart = rslt;
+				
+			return rslt;
+		}
+		
+		/** Returns the total number of characters in the container. This can include text that is not currently in view,
+		 * if the container is scrollable. This value is updated when the text is composed (when the IFlowComposer's <code>compose()</code> 
+		 * or <code>updateAllControllers()</code> methods are called).
+		 * 
+	 	 * @see flashx.textLayout.compose.IFlowComposer
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		public function get textLength():int
+		{
+			return _textLength;
+		}
+		/** @private */
+		tlf_internal function setTextLengthOnly(numChars:int):void
+		{ 
+			if (_textLength != numChars)
+			{
+				_textLength = numChars; 
+				// all following containers must have absoluteStart invalidated
+				if (_absoluteStart != -1)
+				{
+					var composer:IFlowComposer = flowComposer;
+					if (composer)
+					{
+						var idx:int = composer.getControllerIndex(this)+1;
+						while (idx < flowComposer.numControllers)
+						{
+							var controller:ContainerController = composer.getControllerAt(idx++);
+							if (controller._absoluteStart == -1)
+								break;
+							controller._absoluteStart = -1;
+						}
+					}
+				}
+			}
+		}
+		
+		/** @private */
+		tlf_internal function setTextLength(numChars:int):void
+		{
+			CONFIG::debug { assert(numChars >= 0,"bad set textLength"); }
+
+			// If its a scrollable container, and it is the last one, then it gets all the characters even though we might not have composed them all
+			_composeCompleteRatio = 1;
+			if (textFlow)
+			{
+				var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
+				var flowComposer:IFlowComposer = textFlow.flowComposer;
+				if (numChars != 0 && flowComposer.getControllerIndex(this) == flowComposer.numControllers - 1 &&
+					((!verticalText && _verticalScrollPolicy != ScrollPolicy.OFF)||
+					(verticalText && _horizontalScrollPolicy != ScrollPolicy.OFF)))
+				{
+					var containerAbsoluteStart:int = absoluteStart;
+					CONFIG::debug { assert(textFlow.textLength >= containerAbsoluteStart,"ContainerController.setTextLength bad absoluteStart"); }
+					_composeCompleteRatio = (textFlow.textLength-containerAbsoluteStart) / numChars;
+					// _composeCompleteRatio = (textFlow.textLength-containerAbsoluteStart) == numChars ? 1 : 1.1;
+					// var scaledContentHeight:Number = _composeCompleteRatio * _contentHeight;
+					// trace("composeCompleteRatio:",_composeCompleteRatio,"composedContentHeight",_contentHeight,"scaledContentHeight",scaledContentHeight,"textLength",textFlow.textLength,"numChars",numChars);
+					// include all remaining characters in this container when scroll enabled
+					numChars = textFlow.textLength - containerAbsoluteStart;
+				}
+			}
+
+			setTextLengthOnly(numChars); 
+			CONFIG::debug
+			{
+				if (Debugging.debugOn && textFlow)
+					assert(Math.min(textFlow.textLength, absoluteStart)+_textLength <= textFlow.textLength, "container textLength may not extend past end of root element!");
+			}			
+		}
+		
+		/** Updates the text within the container.
+		 * Called after an editing change or composition to keep absoluteStart and textLength up to date.
+		 * @private
+		 */
+		tlf_internal function updateLength(pos:int, lengthToAdd:int):void
+		{
+			CONFIG::debug { assert(_textLength+lengthToAdd >= 0,"bad set textLength"); }
+			setTextLengthOnly(_textLength + lengthToAdd);
+		}
+
+		/** 
+		 * Determines whether the container has text that requires composing. 
+		 *
+		 * @return 	true if the container requires composing.
+		 *
+		 * @includeExample examples\ContainerController_isDamagedExample.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		
+		public function isDamaged():Boolean
+		{
+			return flowComposer.isDamaged(absoluteStart + _textLength);
+		}
+
+		/** called whenever the container attributes are changed.  Mark computed attributes and columnstate as out of date. 
+		 * @private
+		 */
+		tlf_internal function formatChanged():void
+		{
+			// The associated container, if there is one, inherits its container
+			// attributes from here. So we need to tell it that these attributes
+			// have changed.
+			_computedFormat = null;
+			invalidateContents();
+		}
+		
+		/**
+		 *  Removes inlines that should no longer be on the display list and
+		 *  adds inlines that are new to the display list.
+		 *  @private
+		 */
+		 
+		tlf_internal function updateInlineChildren():void
+		{
+		}
+		
+		/** determines the shapechildren in the container and applies VJ. @private */
+		protected function fillShapeChildren(sc:Array,tempSprite:Sprite):void
+		{ 
+			if (_textLength == 0)
+				return;	// none				
+			
+			var wmode:String = effectiveBlockProgression;
+
+			var width:Number = _measureWidth ? _contentWidth : _compositionWidth;
+			var height:Number = _measureHeight ? _contentHeight : _compositionHeight;
+			var scrollAdjustRect:Rectangle;
+			if (wmode == BlockProgression.RL)
+				scrollAdjustRect = new Rectangle(_xScroll - width, _yScroll, width, height);
+			else
+				scrollAdjustRect = new Rectangle(_xScroll, _yScroll, width, height);
+			
+			// If scrolling is turned off, and flow is vertical, then we need to adjust the positions of all the lines. With
+			// scrolling turned on, we don't need to do this because the adjustment is done in the Player when the scrollRect
+			// is set up correctly. But with the scrollRect, we also get clipping, and if scrolling is turned off we want to
+			// have the clipping turned off as well. So in this case we do the adjustment manually so the scrollRect can be null.
+			// NOTE: similar adjustments are made in TextContainerManager
+			var adjustLines:Boolean = (wmode == BlockProgression.RL) &&
+				(_horizontalScrollPolicy == ScrollPolicy.OFF && 
+				_verticalScrollPolicy == ScrollPolicy.OFF);
+				
+			// Iterate over the lines in the container, setting the x and y positions and 
+			// adding them to the list to go into the container. Keep track of the width 
+			// and height of the actual text in the container.
+			var firstLine:int = flowComposer.findLineIndexAtPosition(absoluteStart);
+			var lastLine:int = flowComposer.findLineIndexAtPosition(absoluteStart + _textLength - 1);
+			// Build the list in reverse order and than reverse it at the end.
+			// This fixes bug 2509360 ARGO: Unselectable lines appear while scrolling
+			// new bug filed because this is a small performance hit on the reverse - but this is the safest thing to do late in dev cycle
+			for (var lineIndex:int = firstLine; lineIndex <= lastLine; lineIndex++)
+			{
+				var curLine:TextFlowLine = flowComposer.getLineAt(lineIndex);	
+				if (curLine == null || curLine.controller != this)
+					continue;
+
+				var textLine:TextLine = curLine.createShape(wmode);
+				if (!textLine)
+					continue;
+				
+				CONFIG::debug { assert(textLine == curLine.peekTextLine(),"Bad textLine in fillShapeChildren "+Debugging.getIdentity(textLine)+" "+Debugging.getIdentity(curLine)); }
+					
+				var curBounds:Rectangle = getPlacedTextLineBounds(textLine); 
+				
+				// trace("fillShapeChildren:",lineIndex.toString(),curBounds.toString(),textLine.x.toString(),textLine.y.toString(),scrollRect.toString());
+				if ((wmode == BlockProgression.RL) ? curBounds.x + curBounds.width >= scrollAdjustRect.left && curBounds.x < scrollAdjustRect.x + scrollAdjustRect.width :
+					curBounds.y + curBounds.height >= scrollAdjustRect.top && curBounds.y < scrollAdjustRect.y + scrollAdjustRect.height)	
+				{
+					if (adjustLines)
+					{
+						textLine.x -= scrollAdjustRect.x;
+						textLine.y -= scrollAdjustRect.y;
+					}
+					sc.push(textLine);
+					if (textLine.parent == null)
+						tempSprite.addChild(textLine);
+				}
+			}
+			
+			if (adjustLines)
+			{
+				_contentLeft -= scrollAdjustRect.x;
+				_contentTop  -= scrollAdjustRect.y;
+			}
+		}
+		
+		//--------------------------------------------------------------------------
+		//
+		//  Scrolling
+		//
+		//--------------------------------------------------------------------------
+	
+		/** 
+		 * Specifies the horizontal scrolling policy, which you can set by assigning one of the constants of
+		 * the ScrollPolicy class: ON, OFF, or AUTO.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see ScrollPolicy
+	 	 */
+	 	 
+		public function get horizontalScrollPolicy():String
+		{
+			return _horizontalScrollPolicy;
+		}
+		public function set horizontalScrollPolicy(scrollPolicy:String):void
+		{
+			var newScrollPolicy:String = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_horizontalScrollPolicy, scrollPolicy) as String;
+
+			if (newScrollPolicy != _horizontalScrollPolicy)
+			{
+				_horizontalScrollPolicy = newScrollPolicy;
+				if (_horizontalScrollPolicy == ScrollPolicy.OFF)
+					horizontalScrollPosition = 0;
+				formatChanged();	// scroll policy affects composition
+			}
+		}
+		
+		/** Specifies the vertical scrolling policy, which you can set by assigning one of the constants of the ScrollPolicy
+		 * class: ON, OFF, or, AUTO.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see ScrollPolicy
+		 */
+	 	 
+		public function get verticalScrollPolicy():String
+		{
+			return _verticalScrollPolicy;
+		}
+		public function set verticalScrollPolicy(scrollPolicy:String):void
+		{
+			var newScrollPolicy:String = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_verticalScrollPolicy, scrollPolicy) as String;
+			if (newScrollPolicy != _verticalScrollPolicy)
+			{
+				_verticalScrollPolicy = newScrollPolicy;
+				if (_verticalScrollPolicy == ScrollPolicy.OFF)
+					verticalScrollPosition = 0;
+				formatChanged();	// scroll policy affects composition
+			}
+		}
+		
+		/** Specifies the current horizontal scroll location on the stage. The value specifies the number of
+		 * pixels from the left.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+
+		public function get horizontalScrollPosition():Number
+		{
+			return _xScroll;
+		}
+		
+		public function set horizontalScrollPosition(x:Number):void
+		{
+			if (!_rootElement)
+				return;
+				
+			if (_horizontalScrollPolicy == ScrollPolicy.OFF)
+			{
+				_xScroll = 0;
+				return;
+			}
+			var oldScroll:Number = _xScroll;
+			var newScroll:Number = computeHorizontalScrollPosition(x,true);
+			
+			if (newScroll != oldScroll)
+			{	
+				_shapesInvalid = true;
+				_xScroll = newScroll;
+				updateForScroll();
+			}
+		}
+		
+		static private function pinValue(value:Number, minimum:Number, maximum:Number):Number
+		{
+			return Math.min(Math.max(value, minimum), maximum);						
+		}
+		
+		private function computeHorizontalScrollPosition(x:Number,okToCompose:Boolean):Number
+		{
+			var wmode:String = effectiveBlockProgression;
+			var curEstimatedWidth:Number = contentWidth;
+			var newScroll:Number = 0;
+			
+			if (curEstimatedWidth > _compositionWidth && !_measureWidth)
+			{
+				// Pin the lower and upper bounds of _x. If we're doing vertical text, then the right edge is 0 and the left edge is negative
+				// We may not have composed all the way to the indicated position. If not, force composition so that we can be sure we're at
+				// a legal position.
+				if (wmode == BlockProgression.RL)
+				{
+					newScroll = pinValue(x, _contentLeft + _compositionWidth, _contentLeft + curEstimatedWidth);
+					if (okToCompose && _composeCompleteRatio != 1 && newScroll != _xScroll)
+					{
+						// in order to compose have to set _xScroll
+						_xScroll = x;
+						if (_xScroll > _contentLeft + _contentWidth)
+							_xScroll = _contentLeft + _contentWidth;
+						flowComposer.composeToController(flowComposer.getControllerIndex(this));
+						newScroll = pinValue(x, _contentLeft + _compositionWidth, _contentLeft + _contentWidth);
+					}
+				}
+				else
+					newScroll = pinValue(x, _contentLeft, (_contentLeft + curEstimatedWidth) - _compositionWidth);
+			}
+			return newScroll;
+		}
+
+		
+		/** Specifies the current vertical scroll location on the stage. The value specifies the number of 
+		 * pixels from the top.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+
+		public function get verticalScrollPosition():Number
+		{
+			return _yScroll;
+		}
+
+		public function set verticalScrollPosition(y:Number):void
+		{
+			if (!_rootElement)
+				return;
+				
+			if (_verticalScrollPolicy == ScrollPolicy.OFF)
+			{
+				_yScroll = 0;
+				return;
+			}
+			
+			var oldScroll:Number = _yScroll;
+			var newScroll:Number = computeVerticalScrollPosition(y,true);
+			
+			if (newScroll != oldScroll)
+			{			
+				_shapesInvalid = true;
+				_yScroll = newScroll;
+				updateForScroll();
+			}
+		}	
+		
+		private function computeVerticalScrollPosition(y:Number,okToCompose:Boolean):Number
+		{
+			var newScroll:Number = 0;
+			var curcontentHeight:Number = contentHeight;
+			var wmode:String = effectiveBlockProgression;
+			
+			// Only try to scroll if the content height is greater than the composition height, then there is text that is not visible to scroll to
+			if (curcontentHeight > _compositionHeight)
+			{
+				// new scroll value is somewhere between the topmost content, and the top of the last containerfull
+				newScroll = pinValue(y, _contentTop, _contentTop + (curcontentHeight - _compositionHeight));
+
+				// if we're not composed to the end, compose further so we can scroll to it. Sets the scroll position and then 
+				// recomposes the container, which will compose through the end of the screenfull that starts at the requested position.
+				if (okToCompose && _composeCompleteRatio != 1 && wmode == BlockProgression.TB)
+				{
+					_yScroll = y;
+					if (_yScroll < _contentTop)
+						_yScroll = _contentTop;
+					flowComposer.composeToController(flowComposer.getControllerIndex(this));
+					newScroll = pinValue(y, _contentTop, _contentTop + (curcontentHeight - _compositionHeight));
+				}
+			}
+			return newScroll;
+		}
+		
+		/** 
+		 * Returns the area that the text occupies, as reflected by the last compose or update operation. 
+		 * The width and the height might be estimated, if the container is scrollable and the text exceeds the 
+		 * visible area.
+		 * 
+		 * @return describes the area that the text occupies.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\ContainerController_getContentBoundsExample.as -noswf
+	 	 *
+	 	 * @see flash.geom.Rectangle Rectangle
+	 	 */
+		public function getContentBounds():Rectangle
+		{
+			return new Rectangle(_contentLeft, _contentTop, contentWidth, contentHeight);
+		}
+		
+		/**
+		 * @private
+		 */
+		
+		tlf_internal function get contentLeft():Number
+		{
+			return _contentLeft;
+		}
+		
+		/**
+		 * @private
+		 */
+		
+		tlf_internal function get contentTop():Number
+		{
+			return _contentTop;
+		}
+		
+		/** 
+		 * @private
+		 *
+		 * Returns the vertical extent of the text. For horizontal text, it includes space taken for descenders on the last line. 
+		 * If not all the text is composed, this returns an estimated value based on how much text is already composed; the
+		 * more text that is composed, the more accurate s the estimate. To get a completely accurate value, recompose
+		 * with the rootElement's flowComposer before accessing contentHeight.
+		 * You can get the composed bounds of the text by getting the contentLeft, contentTop, contentWidth, contentHeight properties.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		tlf_internal function get contentHeight():Number
+		{
+			return (effectiveBlockProgression == BlockProgression.TB) ? _contentHeight * _composeCompleteRatio : _contentHeight;
+		}
+		
+		/** 
+		 * @private
+		 *
+		 * Returns the horizontal extent of the text. For vertical text, it includes space taken for descenders on the last line. 
+		 * If not all the text is composed, this returns an estimated value based on how much text is already composed; the
+		 * more text that is composed, the more accurate is the estimate. To get a completely accurate value, recompose
+		 * with the rootElement's flowComposer before accessing contentWidth.
+		 * You can get the composed bounds of the text by getting the contentLeft, contentTop, contentWidth, contentHeight properties.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		tlf_internal function get contentWidth():Number
+		{			
+			return (effectiveBlockProgression == BlockProgression.RL) ? _contentWidth * _composeCompleteRatio : _contentWidth;
+		}
+
+		/** @private */
+		tlf_internal function setContentBounds(contentLeft:Number, contentTop:Number, contentWidth:Number, contentHeight:Number):void
+		{
+			_contentWidth = contentWidth;
+			_contentHeight = contentHeight;
+			_contentLeft = contentLeft;
+			_contentTop = contentTop;
+		}
+
+		private function updateForScroll():void
+		{
+			var flowComposer:IFlowComposer = textFlow.flowComposer;
+			flowComposer.updateToController(flowComposer.getControllerIndex(this));
+	
+			attachTransparentBackgroundForHit(false);
+			
+			// notify client that we scrolled.
+			textFlow.dispatchEvent(new TextLayoutEvent(TextLayoutEvent.SCROLL));
+			
+		//	trace("contentHeight", contentHeight, "contentWidth", contentWidth);
+		//	trace("contentHeight", contentHeight, "contentWidth", contentWidth);
+		}
+				
+		/** @private */
+		CONFIG::debug tlf_internal function validateLines():void
+		{
+			if (!Debugging.containerLineValidation)
+				return;
+			
+			var flowComposer:IFlowComposer = textFlow.flowComposer;
+			var textLine:TextLine;
+			
+			/*for (var ii:int = 0; ii < flowComposer.numLines; ii++)
+			{
+				textLine = flowComposer.getLineAt(ii).peekTextLine()
+				trace("    // flowComposer",ii,textLine ? Debugging.getIdentity(textLine) : "null");
+			}*/
+			
+			// find first textline
+			var numContainerChildren:int = _container.numChildren;
+			for (var containerIndex:int = 0; containerIndex < numContainerChildren; containerIndex++)
+			{
+				textLine = _container.getChildAt(containerIndex) as TextLine;
+				if (textLine)
+					break;
+			}	
+			
+			if (textLine == null)
+				return;	// no lines in this container
+
+			var textFlowLine:TextFlowLine;
+			// find the index of the first line
+			for (var flowComposerIndex:int = 0; flowComposerIndex < flowComposer.numLines; flowComposerIndex++)
+			{
+				textFlowLine = flowComposer.getLineAt(flowComposerIndex);
+				if (textFlowLine.peekTextLine() == textLine)
+					break;
+			}
+			
+			assert(flowComposerIndex != flowComposer.numLines,"BAD FIRST LINE IN CONTAINER");
+			
+			while (containerIndex < numContainerChildren)
+			{
+				textLine = _container.getChildAt(containerIndex) as TextLine;
+				if (textLine == null)
+				{
+					// the very last thing can be the selection sprite
+					assert(containerIndex == numContainerChildren-1,"Wrong location for selectionsprite");
+					assert(_container.getChildAt(containerIndex) == getSelectionSprite(false),"expected selectionsprite but not found");
+					break;
+				}
+				textFlowLine = flowComposer.getLineAt(flowComposerIndex);
+				assert(textLine == textFlowLine.peekTextLine(),"BAD TEXTLINE IN TEXTFLOWLINE");
+				containerIndex++;
+				flowComposerIndex++;
+			}
+		}
+		
+		private function get containerScrollRectLeft():Number
+		{
+			var rslt:Number;
+			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
+				rslt = 0;
+			else
+				rslt= effectiveBlockProgression == BlockProgression.RL ? horizontalScrollPosition - compositionWidth : horizontalScrollPosition;
+			//CONFIG::debug { assert(container.scrollRect == null && rslt == 0 || int(rslt) == container.scrollRect.left,"Bad containerScrollRectLeft"); }
+			return rslt;
+		}
+		
+		private function get containerScrollRectRight():Number
+		{
+			var rslt:Number = containerScrollRectLeft+compositionWidth;
+			//CONFIG::debug { assert(container.scrollRect == null && rslt == compositionWidth || int(rslt) == container.scrollRect.right,"Bad containerScrollRectRight"); }
+			return rslt;
+		}
+				
+		private function get containerScrollRectTop():Number
+		{
+			var rslt:Number;
+			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
+				rslt = 0;
+			else
+				rslt = verticalScrollPosition;;
+			//CONFIG::debug { assert(container.scrollRect == null && rslt == 0 || int(rslt) == container.scrollRect.top,"Bad containerScrollRectTop"); }
+			return rslt;
+		}
+		
+		private function get containerScrollRectBottom():Number
+		{
+			var rslt:Number = containerScrollRectTop+compositionHeight;
+			//CONFIG::debug { assert(container.scrollRect == null && rslt == compositionHeight || int(rslt) == container.scrollRect.bottom,"Bad containerScrollRectBottom"); }
+			return rslt;
+		}
+							
+		/** 
+		 * Scrolls so that the text range is visible in the container.
+		 *
+		 * @param activePosition	The end of the selection that is changed when you extend the selection. It can be
+		 * 	either the start or the end of the selection, expressed as an offset from the start of the text flow.
+		 * @param anchorPosition   	The stable end of the selection when you extend the selection. It can be either 
+		 * 	the start or the end of the selection.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+
+		public function scrollToRange(activePosition:int,anchorPosition:int):void
+		{
+
+			// return if we're not scrolling, or if it's not the last controller
+			if (!_hasScrollRect || !flowComposer || flowComposer.getControllerAt(flowComposer.numControllers-1) != this)
+				return;
+			
+			// clamp values to range absoluteStart,absoluteStart+_textLength
+			var controllerStart:int = absoluteStart;
+			var lastPosition:int = Math.min(controllerStart+_textLength, textFlow.textLength - 1);
+			activePosition = Math.max(controllerStart,Math.min(activePosition,lastPosition));
+			anchorPosition = Math.max(controllerStart,Math.min(anchorPosition,lastPosition));
+								
+			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
+			var begPos:int = Math.min(activePosition,anchorPosition);
+			var endPos:int = Math.max(activePosition,anchorPosition);
+			
+			// is part of the selection in view?
+			var begLineIndex:int = flowComposer.findLineIndexAtPosition(begPos,(begPos == textFlow.textLength));
+			var endLineIndex:int = flowComposer.findLineIndexAtPosition(endPos,(endPos == textFlow.textLength));
+			
+			// no scrolling if any part of the selection is in view
+			var prevLine:TextFlowLine = begLineIndex == 0 ? null : flowComposer.getLineAt(begLineIndex-1);
+			var currLine:TextFlowLine = flowComposer.getLineAt(begLineIndex);
+			var accumulatedIntersection:int = 0;
+			
+			var scrollRectLeft:Number = containerScrollRectLeft;
+			var scrollRectTop:Number  = containerScrollRectTop;
+			var scrollRectRight:Number = containerScrollRectRight;
+			var scrollRectBottom:Number = containerScrollRectBottom;
+			var scrollRect:Rectangle = new Rectangle(scrollRectLeft, scrollRectTop, scrollRectRight-scrollRectLeft, scrollRectBottom-scrollRectTop);
+			
+			for (var lineIndex:int = begLineIndex; lineIndex <= endLineIndex; lineIndex++)
+			{
+				var nextLine:TextFlowLine = lineIndex+1 == flowComposer.numLines ? null : flowComposer.getLineAt(lineIndex+1);
+				var lineEnd:int = currLine.absoluteStart+currLine.textLength;
+				if (currLine.controller == this)
+				{
+					accumulatedIntersection += currLine.selectionWillIntersectScrollRect(scrollRect,begPos,Math.min(lineEnd,endPos),prevLine,nextLine);
+					if (accumulatedIntersection >= 2)
+						return;	// dont scroll
+				}
+				if (lineIndex == endLineIndex)
+					break;
+				prevLine = currLine;
+				currLine = nextLine;
+				begPos = lineEnd;
+			}
+			
+			var rect:Rectangle = posToRectangle(activePosition);
+			if (!rect)
+			{
+				flowComposer.composeToPosition(activePosition);
+				rect = posToRectangle(activePosition);
+			} 
+			if (rect) 
+			{
+				var firstVisibleLine:TextFlowLine;
+				var lastVisibleLine:TextFlowLine;
+
+				// vertical scroll
+				if (rect.top < scrollRectTop)
+					verticalScrollPosition = rect.top;
+				if (verticalText) {					
+					// horizontal scroll
+					if (rect.left < scrollRectLeft)
+						horizontalScrollPosition = rect.left + _compositionWidth;
+					if (rect.right > scrollRectRight)
+						horizontalScrollPosition = rect.right;
+					// set the rect to the previous character for the test on the bottom of the scrollRect.
+					// Note, when dealing with the "bottommost" character (t-to-b), we actually need to position
+					// pos at pos-1 because pos is looking at the character following the insertion point.
+					// However, we can only look at the previous character if we're not on the first character in
+					// a line.
+					// This tests for pos being the first char on a line. If not, reset rect.
+					if (flowComposer.findLineAtPosition(activePosition).absoluteStart != activePosition)
+						rect = posToRectangle(activePosition-1);
+					// If we're showing a blinking insertion point, we need to scroll far enough that
+					// we can see the insertion point, and it comes just after the character.
+					if (activePosition == anchorPosition)
+						rect.bottom += 2;							
+					// vertical scroll
+					if (rect && rect.bottom > scrollRectBottom)
+						verticalScrollPosition = rect.bottom - _compositionHeight;
+					// now, we need to determine if the scrollRect is full or only partially full.
+					// A partially full scrollRect can happen when you're deleting text at the end of the
+					// container. When that happens, the bottomExtreme line in the scrollRect has space between
+					// it and the left edge of the scrollRect. So, if it's partially full, then we need to scroll
+					// to bring more of the Flow into view.
+					var a:Array = findFirstAndLastVisibleLine();
+					firstVisibleLine = a[0];
+					lastVisibleLine = a[1];
+					if (lastVisibleLine && lastVisibleLine.x - lastVisibleLine.descent - lastVisibleLine.spaceAfter > scrollRectLeft)
+						horizontalScrollPosition = lastVisibleLine.x - lastVisibleLine.descent + _compositionWidth;
+				}
+				else 
+				{
+					// vertical scroll
+					if (rect.bottom > scrollRectBottom)
+						verticalScrollPosition = rect.bottom - _compositionHeight;
+					// horizontal scroll
+					if (rect.left < scrollRectLeft)
+						horizontalScrollPosition = rect.left;
+					// set the rect to the previous character for the test on the right side of the scrollRect.
+					// Note, when dealing with the "rightmost" character (l-to-r), we actually need to position
+					// pos at pos-1 because pos is looking at the character following the insertion point.
+					// However, we can only look at the previous character if we're not on the first character in
+					// a line.
+					// This tests for pos being the first char on a line. If not, reset rect.
+					if (flowComposer.findLineAtPosition(activePosition).absoluteStart != activePosition)
+						rect = posToRectangle(activePosition-1);
+					// If we're showing a blinking insertion point, we need to scroll far enough to see the
+					// insertion point, and it comes up to the right
+					if (activePosition == anchorPosition)
+						rect.right += 2;
+					if (rect && rect.right > scrollRectRight)
+						horizontalScrollPosition = rect.right - _compositionWidth;
+					// now, we need to determine if the scrollRect is full or only partially full.
+					// A partially full scrollRect can happen when you're deleting text at the end of the
+					// container. When that happens, the bottomExtreme line in the scrollRect has space between
+					// it and the bottom edge of the scrollRect. So, if it's partially full, then we need to scroll
+					// to bring more of the Flow into view.
+					var b:Array = findFirstAndLastVisibleLine();
+					firstVisibleLine = b[0];
+					lastVisibleLine = b[1];
+					if (rect.top > scrollRectTop && lastVisibleLine && lastVisibleLine.y + lastVisibleLine.height + lastVisibleLine.spaceAfter < scrollRectBottom)
+						verticalScrollPosition = lastVisibleLine.y + lastVisibleLine.height;
+				}
+			}
+		}		
+
+		private function posToRectangle(pos:int):Rectangle
+		{
+			var line:TextFlowLine = flowComposer.findLineAtPosition(pos);
+			// should the textLine ever be null? It is after some operations -- dunno why (rlw)
+			if (!line.textLineExists || line.isDamaged())
+				return null;
+
+
+			var textLine:TextLine = line.getTextLine(true);
+			var atomBounds:Rectangle;
+			var atomIdx:int = textLine.getAtomIndexAtCharIndex(pos-line.paragraph.getAbsoluteStart());
+			CONFIG::debug { assert(atomIdx > -1, "How'd we get here?"); }
+			if (atomIdx > -1) 
+				atomBounds = textLine.getAtomBounds(atomIdx);
+	
+			// special handling for TCY - no line height adjustments TCY is perpendicular to the height direction
+			if (effectiveBlockProgression == BlockProgression.RL)
+			{
+				var leafElement:FlowLeafElement = _rootElement.getTextFlow().findLeaf(pos);
+				if (leafElement.getParentByType(flashx.textLayout.elements.TCYElement) != null)
+					return new Rectangle(line.x+atomBounds.x+line.y+atomBounds.y+atomBounds.width,atomBounds.height);
+			}
+				
+			return effectiveBlockProgression == BlockProgression.RL ? 
+				new Rectangle(line.x, line.y + atomBounds.y, line.height, atomBounds.height) :
+				new Rectangle(line.x + atomBounds.x, line.y-line.height+line.ascent, atomBounds.width, line.height+textLine.descent);
+
+		}
+		
+		/**
+		 * @private
+		 */
+
+		tlf_internal function resetColumnState():void
+		{
+			if (_rootElement)
+				_columnState.updateInputs(effectiveBlockProgression, _rootElement.computedFormat.direction, this, _compositionWidth, _compositionHeight);
+		}
+		
+		/** 
+		 * Marks all the text in this container as needing composing. 
+		 *
+		 * @includeExample examples\ContainerController_invalidateContentsExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		 
+		public function invalidateContents():void
+		{
+			if (textFlow && _textLength)
+				textFlow.damage(absoluteStart, _textLength, FlowDamageType.GEOMETRY, false);
+		}
+		
+		/** @private */
+		private var _transparentBGX:Number;
+		/** @private */
+		private var _transparentBGY:Number;
+		/** @private */
+		private var _transparentBGWidth:Number;
+		/** @private */
+		private var _transparentBGHeight:Number;
+				
+		/** No mouse clicks or moves will be generated for the container unless it has a background covering its area.  Text Layout Framework
+		 * wants those events so that clicking on a container will select the text in it.  This code
+		 * adds or updates (on size change) that background for Sprite containers only. This may cause clients problems 
+		 * - definitely no hits is a problem - add this code to explore the issues - expect feedback.  
+		 * We may have to make this configurable. @private */
+		
+
+		tlf_internal function attachTransparentBackgroundForHit(justClear:Boolean):void
+		{
+			if (_minListenersAttached && attachTransparentBackground)
+			{
+				var s:Sprite = _container as Sprite;
+				if (s)
+				{
+					if (justClear)
+					{
+						s.graphics.clear();
+						CONFIG::debug { Debugging.traceFTECall(null,s,"clearTransparentBackground()"); }
+						_transparentBGX = _transparentBGY = _transparentBGWidth = _transparentBGHeight = NaN;
+					}
+					else
+					{		
+						var bgwidth:Number = _measureWidth ? _contentWidth : _compositionWidth;
+						var bgheight:Number = _measureHeight ? _contentHeight : _compositionHeight;
+						
+						var adjustHorizontalScroll:Boolean = effectiveBlockProgression == BlockProgression.RL && _horizontalScrollPolicy != ScrollPolicy.OFF;
+						var bgx:Number = adjustHorizontalScroll ? _xScroll - bgwidth : _xScroll;
+						var bgy:Number = _yScroll;
+
+						CONFIG::debug { assert(!isNaN(bgx) && !isNaN(bgy) && !isNaN(bgwidth) && ! isNaN(bgheight),"Bad background rectangle"); }
+						
+						if (bgx != _transparentBGX || bgy != _transparentBGY || bgwidth != _transparentBGWidth || bgheight != _transparentBGHeight)
+						{
+							s.graphics.clear();
+							CONFIG::debug { Debugging.traceFTECall(null,s,"clearTransparentBackground()"); }
+							if (bgwidth != 0 && bgheight != 0 )
+							{
+								s.graphics.beginFill(0, 0);
+								s.graphics.drawRect(bgx, bgy, bgwidth, bgheight);
+								s.graphics.endFill();
+								CONFIG::debug { Debugging.traceFTECall(null,s,"drawTransparentBackground",bgx, bgy, bgwidth, bgheight); }
+							}
+							_transparentBGX = bgx;
+							_transparentBGY = bgy;
+							_transparentBGWidth = bgwidth;
+							_transparentBGHeight = bgheight;
+						}
+					}
+				}
+			} 
+		}
+		
+		/** @private */
+		tlf_internal	function interactionManagerChanged(newInteractionManager:ISelectionManager):void
+		{
+			if (newInteractionManager)
+				attachContainer();
+			else
+				detachContainer();
+		}
+				
+		//--------------------------------------------------------------------------
+		//  Event handlers for editing
+		//  Listeners are attached on first compose
+		//--------------------------------------------------------------------------
+				
+		/** @private */
+		tlf_internal function attachContainer():void
+		{
+			if (!_minListenersAttached && textFlow && textFlow.interactionManager)
+			{
+				_minListenersAttached = true;
+				
+				if (_container)
+				{
+		   			_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);
+		   			_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+	    			
+	    			attachTransparentBackgroundForHit(false);
+					
+					// If the container already has focus, we have to attach all listeners
+					if (_container.stage && _container.stage.focus == _container)
+						attachAllListeners();
+				}
+			}
+	 	}
+	 	
+	 	/** @private */
+		tlf_internal function attachInteractionHandlers():void
+		{
+			// the receiver is either this or another class that is going to handle the methods.
+			var receiver:IInteractionEventHandler = getInteractionHandler();
+			
+			// the required handlers are implemented here and forwarded to the receiver
+			_container.addEventListener(MouseEvent.MOUSE_DOWN, requiredMouseDownHandler);
+		   	_container.addEventListener(FocusEvent.FOCUS_OUT, requiredFocusOutHandler);
+			_container.addEventListener(MouseEvent.DOUBLE_CLICK, receiver.mouseDoubleClickHandler);
+			_container.addEventListener(Event.ACTIVATE, receiver.activateHandler);
+		   	_container.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, receiver.focusChangeHandler);
+		   	_container.addEventListener(FocusEvent.KEY_FOCUS_CHANGE, receiver.focusChangeHandler);
+		   	_container.addEventListener(TextEvent.TEXT_INPUT, receiver.textInputHandler);
+		   	_container.addEventListener(MouseEvent.MOUSE_OUT, receiver.mouseOutHandler);
+			_container.addEventListener(MouseEvent.MOUSE_WHEEL, receiver.mouseWheelHandler);
+			_container.addEventListener(Event.DEACTIVATE, receiver.deactivateHandler);
+			// attach by literal event name to avoid Argo dependency
+			// normally this would be IMEEvent.START_COMPOSITION
+			_container.addEventListener("imeStartComposition", receiver.imeStartCompositionHandler);
+
+			if (_container.contextMenu)
+	        	_container.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, receiver.menuSelectHandler);
+		   	_container.addEventListener(Event.COPY, receiver.editHandler);
+		   	_container.addEventListener(Event.SELECT_ALL, receiver.editHandler);
+		   	_container.addEventListener(Event.CUT, receiver.editHandler);
+		   	_container.addEventListener(Event.PASTE, receiver.editHandler);
+		   	_container.addEventListener(Event.CLEAR, receiver.editHandler);
+		}
+		
+	 	/** @private */
+		tlf_internal function removeInteractionHandlers():void
+		{
+			var receiver:IInteractionEventHandler = getInteractionHandler();
+
+			_container.removeEventListener(MouseEvent.MOUSE_DOWN, requiredMouseDownHandler);
+			_container.removeEventListener(FocusEvent.FOCUS_OUT, requiredFocusOutHandler);
+			_container.removeEventListener(MouseEvent.DOUBLE_CLICK, receiver.mouseDoubleClickHandler);
+			_container.removeEventListener(Event.ACTIVATE, receiver.activateHandler);
+			_container.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, receiver.focusChangeHandler);
+			_container.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE, receiver.focusChangeHandler);
+			_container.removeEventListener(TextEvent.TEXT_INPUT, receiver.textInputHandler);
+ 			_container.removeEventListener(MouseEvent.MOUSE_OUT, receiver.mouseOutHandler);
+			_container.removeEventListener(MouseEvent.MOUSE_WHEEL, receiver.mouseWheelHandler);
+			_container.removeEventListener(Event.DEACTIVATE, receiver.deactivateHandler);
+		//	_container.removeEventListener(IMEEvent.IME_START_COMPOSITION, receiver.imeStartCompositionHandler); 
+			// attach by literal event name to avoid Argo dependency
+			_container.removeEventListener("imeStartComposition", receiver.imeStartCompositionHandler); 
+
+	        if (_container.contextMenu) 
+	        	_container.contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, receiver.menuSelectHandler);
+			_container.removeEventListener(Event.COPY, receiver.editHandler); 
+			_container.removeEventListener(Event.SELECT_ALL, receiver.editHandler);
+			_container.removeEventListener(Event.CUT, receiver.editHandler);
+			_container.removeEventListener(Event.PASTE, receiver.editHandler);
+			_container.removeEventListener(Event.CLEAR, receiver.editHandler);
+			
+			clearSelectHandlers();	
+		}
+		
+		/** @private */
+		tlf_internal function detachContainer():void
+		{
+			if (_minListenersAttached)
+			{
+				if (_container)
+				{
+		   			_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);
+		   			_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+
+					if(_allListenersAttached)
+					{
+						removeInteractionHandlers();				
+						_container.contextMenu = null;
+						
+						attachTransparentBackgroundForHit(true);
+						_allListenersAttached = false;
+					}
+	  			 }
+	  			 _minListenersAttached = false;
+	  		}
+ 	 	}
+		
+		private function attachAllListeners():void
+		{	
+			if (!_allListenersAttached && textFlow && textFlow.interactionManager)
+			{
+				CONFIG::debug { assert(_minListenersAttached,"Bad call to attachAllListeners - won't detach"); }
+				_allListenersAttached = true;
+				if (_container)
+				{
+					_container.contextMenu = createContextMenu();
+					attachInteractionHandlers();
+				}
+			}
+		}
+		
+		/** @private  
+		 *
+		 * Shared so that TextContainerManager can create the same ContextMenu. 
+		 */
+		static tlf_internal function createDefaultContextMenu():ContextMenu
+		{
+			var contextMenu:ContextMenu = new ContextMenu();
+			contextMenu.clipboardMenu = true;
+			contextMenu.clipboardItems.clear = true;
+			contextMenu.clipboardItems.copy = true;
+			contextMenu.clipboardItems.cut = true;
+			contextMenu.clipboardItems.paste = true;
+			contextMenu.clipboardItems.selectAll = true;
+			return contextMenu;
+		}
+		
+		/** 
+		 * Creates a context menu for the ContainerController. Use the methods of the ContextMenu class to 
+		 * add items to the menu.
+		 * <p>You can override this method to define a custom context menu.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flash.ui.ContextMenu ContextMenu
+	 	 */
+		protected function createContextMenu():ContextMenu
+		{
+			return createDefaultContextMenu();
+		}
+		
+		/** @private */
+		tlf_internal function scrollTimerHandler(event:Event):void
+		{
+			// trace("BEGIN scrollTimerHandler");
+			if (!_scrollTimer)
+				return;
+
+			// shut it down if not in this container
+			if (textFlow.interactionManager == null || textFlow.interactionManager.activePosition < absoluteStart || textFlow.interactionManager.activePosition > absoluteStart+textLength)
+				event = null;
+				
+						
+			// We're listening for MOUSE_UP so we can cancel autoscrolling
+			if (event is MouseEvent)
+			{
+				_scrollTimer.stop();
+				_scrollTimer.removeEventListener(TimerEvent.TIMER, scrollTimerHandler);
+				CONFIG::debug { assert(_container.stage ==  null || getContainerRoot() == event.currentTarget,"scrollTimerHandler bad target"); }
+				event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, scrollTimerHandler);
+				_scrollTimer = null;
+			}
+			else if (!event)
+			{
+				_scrollTimer.stop();
+				_scrollTimer.removeEventListener(TimerEvent.TIMER, scrollTimerHandler);
+				if (getContainerRoot())
+					getContainerRoot().removeEventListener(	MouseEvent.MOUSE_UP, scrollTimerHandler);	
+				_scrollTimer = null;
+			}
+			else if (_container.stage)
+			{
+				var containerPoint:Point = new Point(_container.stage.mouseX, _container.stage.mouseY);
+				containerPoint = _container.globalToLocal(containerPoint);
+				var scrollChange:int = autoScrollIfNecessaryInternal(containerPoint);
+				if (scrollChange != 0 && interactionManager)		// force selection update if we actually scrolled and we have a selection manager
+				{
+					var mouseEvent:MouseEvent = new PsuedoMouseEvent(MouseEvent.MOUSE_MOVE,false,false,_container.stage.mouseX, _container.stage.mouseY,_container.stage,false,false,false,true);
+					var stashedScrollTimer:Timer = _scrollTimer;	
+					try
+					{
+						_scrollTimer =  null;
+						interactionManager.mouseMoveHandler(mouseEvent);
+					}
+					catch (e:Error)
+					{
+						throw(e);
+					}
+					finally
+					{
+						_scrollTimer = stashedScrollTimer;
+					}
+				}
+			}
+			// trace("AFTER scrollTimerHandler");
+		}
+
+		/** 
+		 * Handle a scroll event during a "drag" selection. 
+		 *
+		 * @param mouseX	The horizontal position of the mouse cursor on the stage.
+		 * @param mouseY	The vertical position of the mouse cursor  on the stage.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		public function autoScrollIfNecessary(mouseX:int, mouseY:int):void
+		{ 			
+ 			if (flowComposer.getControllerAt(flowComposer.numControllers-1) != this)
+ 			{
+ 				var verticalText:Boolean = (effectiveBlockProgression == BlockProgression.RL);
+ 				var lastController:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1);
+ 				if ((verticalText && _horizontalScrollPolicy == ScrollPolicy.OFF) ||
+ 					(!verticalText && _verticalScrollPolicy == ScrollPolicy.OFF))
+					return;
+				var r:Rectangle = lastController.container.getBounds(_container.stage);
+				if (verticalText)
+				{
+					if (mouseY >= r.top && mouseY <= r.bottom)
+						lastController.autoScrollIfNecessary(mouseX, mouseY);
+				}
+				else
+				{
+					if (mouseX >= r.left && mouseX <= r.right)
+						lastController.autoScrollIfNecessary(mouseX, mouseY);
+				}
+ 			}
+			
+			// even if not the last container - may scroll if there are explicit linebreaks
+			if (!_hasScrollRect)
+				return;
+			var containerPoint:Point = new Point(mouseX, mouseY);
+			containerPoint = _container.globalToLocal(containerPoint); 			
+			autoScrollIfNecessaryInternal(containerPoint);
+		}
+
+		/** 
+		 * Handle a scroll event during a "drag" selection. 
+		 *
+		 * @param mouseX	The horizontal position of the mouse cursor on the stage.
+		 * @param mouseY	The vertical position of the mouse cursor  on the stage.
+		 * @returns positive number if scroll went forward in reading order, negative number if it went backwards, and 0 if no scroll
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		 
+		private function autoScrollIfNecessaryInternal(extreme:Point):int
+		{
+			CONFIG::debug 
+			{ 
+				assert(_hasScrollRect, "internal scrolling function called on non-scrollable container");
+			}
+				
+			
+			var scrollDirection:int = 0;
+			
+			if (extreme.y - containerScrollRectBottom > 0) {
+				verticalScrollPosition += textFlow.configuration.scrollDragPixels;
+				scrollDirection = 1;
+			}
+			else if (extreme.y - containerScrollRectTop < 0) {
+				verticalScrollPosition -= textFlow.configuration.scrollDragPixels;
+				scrollDirection = -1;
+			}
+				
+			if (extreme.x - containerScrollRectRight > 0) {
+				horizontalScrollPosition += textFlow.configuration.scrollDragPixels;
+				scrollDirection = -1;
+			}
+			else if (extreme.x - containerScrollRectLeft < 0) {
+				horizontalScrollPosition -= textFlow.configuration.scrollDragPixels;
+				scrollDirection = 1;
+			}
+
+			// we need a timer so that the mouse doesn't have to continue moving when the mouse is outside the content area
+			if (scrollDirection != 0 && !_scrollTimer) 
+			{
+				_scrollTimer = new Timer(textFlow.configuration.scrollDragDelay);	// 35 ms is the default auto-repeat interval for ScrollBars.
+				_scrollTimer.addEventListener(TimerEvent.TIMER, scrollTimerHandler, false, 0, true);
+				if (getContainerRoot())
+				{
+					getContainerRoot().addEventListener(MouseEvent.MOUSE_UP, scrollTimerHandler, false, 0, true);
+					beginMouseCapture(); // TELL CLIENTS WE WANT mouseUpSomewhere events
+				}
+				_scrollTimer.start();
+			}
+			
+			return scrollDirection;
+		}
+
+		/** @private */
+		tlf_internal function findFirstAndLastVisibleLine():Array
+		{
+			var firstLine:int = flowComposer.findLineIndexAtPosition(absoluteStart);
+			var lastLine:int = flowComposer.findLineIndexAtPosition(absoluteStart + _textLength - 1);
+			var lastColumn:int = _columnState.columnCount - 1;
+			var firstVisibleLine:TextFlowLine;
+			var lastVisibleLine:TextFlowLine;
+			
+			// no visible lines?
+			if (firstLine == flowComposer.numLines)
+				return [null,null];
+				
+			for (var lineIndex:int = firstLine; lineIndex <= lastLine; lineIndex++) 
+			{
+				var curLine:TextFlowLine = flowComposer.getLineAt(lineIndex);	
+				if (curLine.controller != this)
+					continue;
+			
+				// skip until we find the lines in the last column
+				if (curLine.columnIndex != lastColumn)
+					continue;
+			
+				if (curLine.textLineExists)
+				{
+					var curTextLine:TextLine = curLine.getTextLine();
+					if (curTextLine && curTextLine.parent)
+					{
+						if (!firstVisibleLine)
+							firstVisibleLine = curLine;
+							
+						lastVisibleLine = curLine;
+					}
+				}		
+			}
+			
+			return [firstVisibleLine, lastVisibleLine];
+		}
+		
+		/** 
+		* Figure out the scroll distance required to scroll up or down by the specified number of lines.
+		* Negative numbers scroll upward, bringing more of the top of the TextFlow into view. Positive numbers 
+		* scroll downward, bringing the next line from the bottom into full view.
+		* 
+		* <p>When scrolling up, for example, the method makes the next line fully visible. If the next line is partially
+		* obscured and the number of lines specified is 1, the partially obscured line becomes fully visible.</p>
+		*
+		* @param nLines	The number of lines to scroll.
+		*
+		* @return 	the delta amount of space to scroll
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+		 
+		public function getScrollDelta(numLines:int):Number
+		{
+			if (flowComposer.numLines == 0)
+				return 0;
+
+			// Now we want to calculate the top & bottom lines within the scrollRect. It's ok if they're just partially
+			// visible. Once we determine these lines, we figure out how much we need to scroll in order to bring the
+			// lines completely into view.
+			
+			var a:Array = findFirstAndLastVisibleLine();
+			var firstVisibleLine:TextFlowLine = a[0];
+			var lastVisibleLine:TextFlowLine = a[1];
+			// trace("    // findFirstAndLastVisibleLine ",flowComposer.findLineIndexAtPosition(firstVisibleLine.absoluteStart),flowComposer.findLineIndexAtPosition(lastVisibleLine.absoluteStart));
+						
+			var newLineIndex:int;
+			var lineIndex:int;
+			if (numLines > 0) 
+			{
+				lineIndex = flowComposer.findLineIndexAtPosition(lastVisibleLine.absoluteStart);
+				// If the last visible line is only partly visible, don't count it as visible. But make sure it overlaps by
+				// at least two pixels, otherwise it doesn't look like its clipped.
+				if (lastVisibleLine)
+				{
+					var lastTextLine:TextLine = lastVisibleLine.getTextLine(true);
+					if (effectiveBlockProgression == BlockProgression.TB)
+					{
+						if ((lastTextLine.y + lastTextLine.descent) - containerScrollRectBottom > 2)
+							--lineIndex;
+					}
+					else if (containerScrollRectLeft - (lastTextLine.x - lastTextLine.descent)  > 2)
+						--lineIndex;
+				}
+
+				// if we hit the end, force composition so that we get more lines - I picked a random amount to scroll forward, if its not enough, it will keep going
+				while (lineIndex + numLines > flowComposer.numLines - 1 && flowComposer.damageAbsoluteStart < textFlow.textLength)	
+					flowComposer.composeToPosition(flowComposer.damageAbsoluteStart + 1000);
+				newLineIndex = Math.min(flowComposer.numLines-1, lineIndex + numLines);
+			}
+			if (numLines < 0) 
+			{
+				lineIndex = flowComposer.findLineIndexAtPosition(firstVisibleLine.absoluteStart);
+
+				// If the first visible line is only partly visible, don't count it as visible. But make sure it overlaps by
+				// at least two pixels, otherwise it doesn't look like its clipped.
+				if (firstVisibleLine)
+				{
+					if (effectiveBlockProgression == BlockProgression.TB)
+					{
+						if (firstVisibleLine.y + 2 < containerScrollRectTop)
+							++lineIndex;
+					}
+					else if (firstVisibleLine.x + firstVisibleLine.ascent > containerScrollRectRight + 2)
+						++lineIndex;
+				} 
+
+				newLineIndex = Math.max(0, lineIndex + numLines);
+			}
+			
+			var line:TextFlowLine = flowComposer.getLineAt(newLineIndex);
+			if (line.absoluteStart < absoluteStart)		// don't scroll past the start of this controller -- previous text is in previous controller
+				return 0;
+			if (line.validity != TextLineValidity.VALID)
+			{
+				var leaf:FlowLeafElement = textFlow.findLeaf(line.absoluteStart);
+				var paragraph:ParagraphElement = leaf.getParagraph();
+				textFlow.flowComposer.composeToPosition(paragraph.getAbsoluteStart() + paragraph.textLength);
+				line = flowComposer.getLineAt(newLineIndex);
+				CONFIG::debug { assert(line.validity == TextLineValidity.VALID, "expected valid line after recomposing"); }
+			}
+			
+			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
+
+			var newScrollPosition:Number;
+			if (verticalText)
+			{
+				
+				newScrollPosition =  numLines < 0 ? line.x + line.textHeight : line.x - line.descent + _compositionWidth;
+				return newScrollPosition - horizontalScrollPosition;
+			}
+
+			newScrollPosition = numLines < 0 ? line.y : line.y + line.textHeight - _compositionHeight;
+			return newScrollPosition - verticalScrollPosition;
+		}
+		
+		/** 
+		 * Processes the <code>MouseEvent.MOUSE_OVER</code> event when the client manages events. 
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_mouseOverHandlerExample.as -noswf
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_OVER MouseEvent.MOUSE_OVER
+		 */
+		 
+		public function mouseOverHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+				interactionManager.mouseOverHandler(event);
+		}
+
+		/** @private Does required mouseOver handling.  Calls mouseOverHandler.  @see #mouseOverHandler */
+		tlf_internal function requiredMouseOverHandler(event:MouseEvent):void
+		{
+			attachAllListeners();
+			getInteractionHandler().mouseOverHandler(event);
+		}
+
+		/** Processes the <code>MouseEvent.MOUSE_OUT</code> event when the client manages events.
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_OUT MouseEvent.MOUSE_OUT
+		 */				
+		public function mouseOutHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+				interactionManager.mouseOutHandler(event);
+		}
+		
+		/** Processes the <code>MouseEvent.MOUSE_WHEEL</code> event when the client manages events.
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_WHEEL MouseEvent.MOUSE_WHEEL
+		 */
+		public function mouseWheelHandler(event:MouseEvent):void
+		{
+			// Do the scroll and call preventDefault only if the there is enough text to scroll. Otherwise
+			// we let the event bubble up and cause scrolling at the next level up in the client's container hierarchy.
+			var verticalText:Boolean = effectiveBlockProgression == BlockProgression.RL;
+			if (verticalText)
+			{
+				if (contentWidth > _compositionWidth && !_measureWidth)
+				{
+					horizontalScrollPosition += event.delta * textFlow.configuration.scrollMouseWheelMultiplier;
+					event.preventDefault();
+				}
+			}
+			else if (contentHeight > _compositionHeight && !_measureHeight)
+			{
+				verticalScrollPosition -= event.delta * textFlow.configuration.scrollMouseWheelMultiplier;
+				event.preventDefault();
+			}
+		}
+		
+		
+		/** Processes the <code>MouseEvent.MOUSE_DOWN</code> event when the client manages events. 
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_DOWN MouseEvent.MOUSE_DOWN
+		 */
+		 
+		public function mouseDownHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+			{
+				interactionManager.mouseDownHandler(event);
+				// grab the focus - alternative is to listen to keyevents on the Application
+				// is this necessary?
+				if ( interactionManager.hasSelection())
+					setFocus();
+			}
+		}
+
+		/** @private Does required mouseDown handling.  Calls mouseDownHandler.  @see #mouseDownHandler */
+		tlf_internal function requiredMouseDownHandler(event:MouseEvent):void
+		{
+			if (!_selectListenersAttached)
+			{
+				var containerRoot:DisplayObject = getContainerRoot();
+				if (containerRoot)
+				{
+		   			containerRoot.addEventListener(MouseEvent.MOUSE_MOVE, rootMouseMoveHandler, false, 0, true); 
+					containerRoot.addEventListener(MouseEvent.MOUSE_UP,   rootMouseUpHandler, false, 0, true);
+					
+					beginMouseCapture(); // TELL CLIENTS THAT WE WANT moueUpSomewhere EVENTS
+					
+	
+					_selectListenersAttached = true;
+				}
+			}
+			getInteractionHandler().mouseDownHandler(event); 
+		}
+		
+		/** 
+		 * Processes the <code>MouseEvent.MOUSE_UP</code> event when the client manages events.
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_UP MouseEvent.MOUSE_UP
+		 *
+		 */
+		public function mouseUpHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+			{
+				interactionManager.mouseUpHandler(event);
+			}
+		}		
+		
+		/** @private */
+		tlf_internal function rootMouseUpHandler(event:MouseEvent):void
+		{
+			clearSelectHandlers();
+			getInteractionHandler().mouseUpHandler(event);
+		}
+		
+				
+		private function clearSelectHandlers():void
+		{	
+			if (_selectListenersAttached)
+			{
+				CONFIG::debug { assert(getContainerRoot() != null,"No container root"); }
+   				getContainerRoot().removeEventListener(MouseEvent.MOUSE_MOVE, rootMouseMoveHandler); 					
+				getContainerRoot().removeEventListener(MouseEvent.MOUSE_UP,   rootMouseUpHandler);
+				endMouseCapture(); // TELL CLIENTS WE NO LONGER WANT mouseUpSomewhere EVENTS
+				_selectListenersAttached = false;
+			}
+		}
+
+		/** 
+		 * Called to request clients to begin the forwarding of mouseup and mousemove events from outside a security sandbox.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function beginMouseCapture():void
+		{
+			// trace("BEGIN MOUSECAPTURE");
+			var sandboxManager:ISandboxSupport = getInteractionHandler() as ISandboxSupport
+			if (sandboxManager && sandboxManager != this)
+				sandboxManager.beginMouseCapture();
+		}
+		/** 
+		 * Called to inform clients that the the forwarding of mouseup and mousemove events from outside a security sandbox is no longer needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		 public function endMouseCapture():void
+		{
+			// trace("END MOUSECAPTURE");
+			var sandboxManager:ISandboxSupport = getInteractionHandler() as ISandboxSupport
+			if (sandboxManager && sandboxManager != this)
+				sandboxManager.endMouseCapture();
+		}
+		/** Client call to forward a mouseUp event from outside a security sandbox.  Coordinates of the mouse up are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function mouseUpSomewhere(event:Event):void
+		{
+			rootMouseUpHandler(null);
+			scrollTimerHandler(null);
+		}
+		/** Client call to forward a mouseMove event from outside a security sandbox.  Coordinates of the mouse move are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function mouseMoveSomewhere(event:Event):void
+		{
+			return;	// do nothing right now
+		}
+
+		// What'd I hit???
+		private function hitOnMyFlowExceptLastContainer(event:MouseEvent):Boolean
+		{
+			if (event.target is TextLine)
+			{
+				var tfl:TextFlowLine = TextLine(event.target).userData as TextFlowLine;
+				if (tfl)
+				{
+					var para:ParagraphElement = tfl.paragraph;
+					if(para.getTextFlow() == textFlow)
+						return true;
+				}
+			}
+			else if (event.target is Sprite)
+			{
+				// skip the last container in the chain
+				for (var idx:int = 0; idx < textFlow.flowComposer.numControllers-1; idx++)
+					if (textFlow.flowComposer.getControllerAt(idx).container == event.target)
+						return true;
+			}
+			return false;
+		}
+		/** 
+		 * Processes the <code>MouseEvent.MOUSE_MOVE</code> event when the client manages events.
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.MouseEvent#MOUSE_MOVE MouseEvent.MOUSE_MOVE
+		 */
+		 
+		public function mouseMoveHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+			{
+				// only autoscroll if we haven't hit something on the stage related to this particular TextFlow
+				if (event.buttonDown && !hitOnMyFlowExceptLastContainer(event))
+					autoScrollIfNecessary(event.stageX, event.stageY);
+				interactionManager.mouseMoveHandler(event);
+			}
+		}
+		
+		/** @private */
+		tlf_internal function rootMouseMoveHandler(event:MouseEvent):void
+		{   
+			getInteractionHandler().mouseMoveHandler(event); 
+		}
+		
+		/** Processes the <code>MouseEvent.DOUBLE_CLICK</code> event when the client manages events.
+		 *
+		 * @param event The MouseEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_mouseDoubleClickHandlerExample.as -noswf
+		 *
+		 * @see flash.events.MouseEvent#DOUBLE_CLICK MouseEvent.DOUBLE_CLICK
+		 */
+		public function mouseDoubleClickHandler(event:MouseEvent):void
+		{
+			if (interactionManager)
+			{
+				interactionManager.mouseDoubleClickHandler(event);
+				// grab the focus - alternative is to listen to keyevents on the Application
+				// is this necessary?
+				if ( interactionManager.hasSelection())
+					setFocus();
+			}
+		}
+		
+		/** Give focus to the text container. @private */
+		tlf_internal function setFocus():void
+		{
+			//trace("setFocus container", id);
+			if (_container.stage)
+				_container.stage.focus = _container; 
+		}
+		
+		private function getContainerController(container:DisplayObject):ContainerController
+		{
+			while (container)
+			{
+				var flowComposer:IFlowComposer = flowComposer;
+				for (var i:int = 0; i < flowComposer.numControllers; i++)
+				{
+					var controller:ContainerController = flowComposer.getControllerAt(i);
+					if (controller.container == container)
+						return controller;
+				}
+				container = container.parent;
+			}
+			return null;
+		}
+		
+		/** 
+		 * Processes the <code>FocusEvent.KEY_FOCUS_CHANGE</code> and <code>FocusEvent.MOUSE_FOCUS_CHANGE</code> events
+		 * when the client manages events.
+		 *
+		 * @param event The FocusEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.FocusEvent#KEY_FOCUS_CHANGE FocusEvent.KEY_FOCUS_CHANGE
+		 * @see flash.events.FocusEvent#MOUSE_FOCUS_CHANGE FocusEvent.MOUSE_FOCUS_CHANGE
+		 */
+		
+		public function focusChangeHandler(event:FocusEvent):void
+		{
+			// Figure out which controllers, if any, correspond to the DisplayObjects passed in the event.
+			// Disallow the focus change if it comes back to this controller again -- this prevents
+			// a focusOut followed by a focusIn, which we would otherwise get after clicking in the 
+			// container that already has focus.
+			
+				// This is the controller that currently has the focus
+			var focusController:ContainerController = getContainerController(DisplayObject(event.target));
+			
+				// This is the controller that is about to get the focus
+			var newFocusController:ContainerController = getContainerController(event.relatedObject);
+
+			/*trace("focusChange from controller", 
+				focusController is ContainerControllerBase ? ContainerControllerBase(focusController).id : "unknownType", 
+				newFocusController is ContainerControllerBase ? ContainerControllerBase(newFocusController).id : "unknownType");
+		*/
+			if (newFocusController == focusController)
+			{
+			//	trace("prevent focus change");
+				event.preventDefault();
+			}
+		}
+		
+		/** Processes the <code>FocusEvent.FOCUS_IN</code> event when the client manages events.
+		 *
+		 * @param event The FocusEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_focusInHandlerExample.as -noswf
+		 *
+		 * @see flash.events.FocusEvent#FOCUS_IN FocusEvent.FOCUS_IN
+		 */
+		public function focusInHandler(event:FocusEvent):void
+		{
+			var blinkRate:int = 0;
+		//	trace("container", id, "focusIn");
+			if (interactionManager)
+			{
+				interactionManager.focusInHandler(event);
+
+				if (interactionManager.editingMode == EditingMode.READ_WRITE)
+					blinkRate = interactionManager.focusedSelectionFormat.pointBlinkRate;				
+			} 
+			setBlinkInterval(blinkRate);
+		}
+		
+		/** @private - does whatever focusIn handling is required and cannot be overridden */
+		tlf_internal function requiredFocusInHandler(event:FocusEvent):void
+		{
+			attachAllListeners();
+			// trace("ContainerController requiredFocusInHandler adding key handlers");
+  			_container.addEventListener(KeyboardEvent.KEY_DOWN, getInteractionHandler().keyDownHandler);
+   			_container.addEventListener(KeyboardEvent.KEY_UP,   getInteractionHandler().keyUpHandler);		
+   			_container.addEventListener(FocusEvent.KEY_FOCUS_CHANGE,   getInteractionHandler().keyFocusChangeHandler);		
+			getInteractionHandler().focusInHandler(event);
+		}
+		
+		/** Processes the <code>FocusEvent.FOCUS_OUT</code> event when the client manages events.
+		 *
+		 * @param event The FocusEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.FocusEvent#FOCUS_OUT FocusEvent.FOCUS_OUT
+		 */
+		 
+		public function focusOutHandler(event:FocusEvent):void
+		{
+			if (interactionManager)
+			{
+				interactionManager.focusOutHandler(event);
+				setBlinkInterval(interactionManager.unfocusedSelectionFormat.pointBlinkRate);
+			}
+			else
+				setBlinkInterval(0);
+		}
+
+		/** @private Does required focusOut handling.  Calls focusOutHandler.  @see #focusOutHandler */
+		tlf_internal function requiredFocusOutHandler(event:FocusEvent):void
+		{
+			// trace("ContainerController requiredFocusOutHandler removing key handlers");
+ 			_container.removeEventListener(KeyboardEvent.KEY_DOWN, getInteractionHandler().keyDownHandler);
+   			_container.removeEventListener(KeyboardEvent.KEY_UP,   getInteractionHandler().keyUpHandler);   			
+   			_container.removeEventListener(FocusEvent.KEY_FOCUS_CHANGE,   getInteractionHandler().keyFocusChangeHandler);   			
+			getInteractionHandler().focusOutHandler(event);
+		}
+		
+		/** Processes the <code>Event.ACTIVATE</code> event when the client manages events.
+		 *
+		 * @param event The Event object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_activateHandlerExample.as -noswf
+		 *
+		 * @see flash.events.Event#ACTIVATE Event.ACTIVATE
+		 */						
+		public function activateHandler(event:Event):void
+		{
+			if (interactionManager)
+				interactionManager.activateHandler(event);
+		}
+		
+		/** Processes the <code>Event.DEACTIVATE</code> event when the client manages events. 
+		 *
+		 * @param event The Event object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.events.Event#DEACTIVATE Event.DEACTIVATE
+		 */
+		 
+		public function deactivateHandler(event:Event):void
+		{
+			if (interactionManager)
+				interactionManager.deactivateHandler(event);
+		}		
+		
+		/** Processes the <code>KeyboardEvent.KEY_DOWN</code> event when the client manages events.
+		 *
+		 * @param The KeyboardEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.KeyboardEvent#KEY_DOWN KeyboardEvent.KEY_DOWN
+		 */
+		public function keyDownHandler(event:KeyboardEvent):void
+		{
+			if (interactionManager)
+				interactionManager.keyDownHandler(event);
+		}
+		
+		/** Processes the <code>Keyboard.KEY_UP</code> event when the client manages events.
+		 *
+		 * @param event The KeyboardEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_keyUpHandlerExample.as -noswf
+		 *
+		 * @see flash.events.KeyboardEvent#KEY_UP KeyboardEvent.KEY_UP
+		 */
+		 
+		public function keyUpHandler(event:KeyboardEvent):void
+		{
+			if (interactionManager)
+				interactionManager.keyUpHandler(event);
+		}
+
+		/** Processes the <code>FocusEvent.KEY_FOCUS_CHANGE</code> event when the client manages events.
+		 *
+		 * @param event The FocusEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.events.FocusEvent#KEY_FOCUS_CHANGE FocusEvent.KEY_FOCUS_CHANGE
+		 */
+		public function keyFocusChangeHandler(event:FocusEvent):void
+		{
+			if (interactionManager)
+				interactionManager.keyFocusChangeHandler(event);
+		}		
+		/** Processes the <code>TextEvent.TEXT_INPUT</code> event when the client manages events.
+		 *
+		 * @param event  The TextEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @includeExample examples\ContainerController_textInputHandlerExample.as -noswf
+		 *
+		 * @see flash.events.TextEvent#TEXT_INPUT TextEvent.TEXT_INPUT
+		 */
+		 
+		public function textInputHandler(event:TextEvent):void
+		{
+			if (interactionManager)
+				interactionManager.textInputHandler(event);
+		}
+		
+		/** Processes the <code>IMEEvent.IME_START_COMPOSITION</code> event when the client manages events.
+		 *
+		 * @param event  The IMEEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.events.IMEEvent.IME_START_COMPOSITION
+		 */
+		 
+		public function imeStartCompositionHandler(event:IMEEvent):void
+		{
+			if (interactionManager)
+				interactionManager.imeStartCompositionHandler(event);
+		}
+		
+		
+		/** 
+		 * Processes the <code>ContextMenuEvent.MENU_SELECT</code> event when the client manages events.
+		 * 
+		 * @param The ContextMenuEvent object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_menuSelectHandlerExample.as -noswf
+		 * 
+		 * @see flash.events.ContextMenuEvent#MENU_SELECT ContextMenuEvent.MENU_SELECT
+		 */						
+		public function menuSelectHandler(event:ContextMenuEvent):void
+		{
+			var tf:DisplayObjectContainer = _container as DisplayObjectContainer;
+
+			if (interactionManager)
+			{
+				interactionManager.menuSelectHandler(event);
+			}
+    		else
+    		{
+				var cbItems:ContextMenuClipboardItems = tf.contextMenu.clipboardItems
+				cbItems.copy = false;
+				cbItems.cut = false;
+				cbItems.paste = false;
+				cbItems.selectAll = false;
+				cbItems.clear = false;
+			}
+		}
+		
+		/**
+		 * Processes an edit event (CUT, COPY, PASTE, SELECT_ALL) when the client manages events.
+		 * 
+		 * @param The Event object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\ContainerController_editHandlerExample.as -noswf
+		 * 
+		 * @see flash.events.Event Event
+		 */	
+			    
+	    	public function editHandler(event:Event):void
+	    	{
+	    		if (interactionManager)
+	    			interactionManager.editHandler(event);
+
+	    		// re-enable context menu so following keyboard shortcuts will work
+	    		var contextMenu:ContextMenu = _container.contextMenu;
+	    		if (contextMenu)
+	    		{
+					contextMenu.clipboardItems.clear = true;
+					contextMenu.clipboardItems.copy = true;
+					contextMenu.clipboardItems.cut = true;
+					contextMenu.clipboardItems.paste = true;
+					contextMenu.clipboardItems.selectAll = true;
+	    		}
+	    	}
+	    
+		 /** 
+		 * Sets the range of selected text in a component implementing ITextSupport.
+		 * If either of the arguments is out of bounds the selection should not be changed.
+		 * Components which wish to support inline IME should call into this method.
+		 * 
+		 * @param anchorIndex The zero-based index value of the character at the anchor end of the selection
+		 *
+		 * @param activeIndex The zero-based index value of the character at the active end of the selection.
+		 * 
+		 * @playerversion Flash 10.0
+		 * @langversion 3.0
+		 */
+	    public function selectRange(anchorIndex:int, activeIndex:int):void
+	    {
+	    	if(interactionManager && interactionManager.editingMode != EditingMode.READ_ONLY)
+	    	{
+		    	interactionManager.selectRange(anchorIndex, activeIndex);
+	    	}
+	    }
+	    
+		//--------------------------------------------------------------------------
+		//
+		//  Cursor blinking code
+		//
+		//--------------------------------------------------------------------------
+		
+		// TODO Want to evaluate whether there's a cleaner way to do this
+		
+		private var blinkTimer:Timer;
+		private var blinkObject:DisplayObject;
+
+		/**
+		 * Starts a DisplayObject cursor blinking by changing its alpha value
+		 * over time.
+		 * 
+		 * @param obj The DisplayObject to use as the cursor.
+		 * 
+		 */
+		private function startBlinkingCursor(obj:DisplayObject, blinkInterval:int):void
+		{
+			if (!blinkTimer)
+				blinkTimer = new Timer(blinkInterval,0);
+			blinkObject = obj;
+			blinkTimer.addEventListener(TimerEvent.TIMER,blinkTimerHandler, false, 0, true);
+			blinkTimer.start();
+		}
+
+		/**
+		 * Stops cursor from blinking
+		 * @private
+		 */
+		protected function stopBlinkingCursor():void
+		{
+			if (blinkTimer)
+				blinkTimer.stop();
+			blinkObject = null;
+		}	
+		
+		private function blinkTimerHandler(event:TimerEvent):void
+		{
+			blinkObject.alpha = (blinkObject.alpha == 1.0) ? 0.0 : 1.0;
+		}
+		
+		/** 
+		 * Set the blink interval.
+		 * 
+		 * @param intervalMS - number of microseconds between blinks
+		 * @private
+		 */
+		protected function setBlinkInterval(intervalMS:int):void
+		{
+			var blinkInterval:int = intervalMS;
+			if (blinkInterval == 0)
+			{
+				// turn off the blinking
+				if (blinkTimer)
+					blinkTimer.stop();
+				if (blinkObject)
+					blinkObject.alpha = 1.0;
+			}
+			else if (blinkTimer)
+			{
+				blinkTimer.delay = blinkInterval;
+				if (blinkObject)
+					blinkTimer.start();
+			}
+		}
+		
+		/** Draw the caret for a selection 
+		 * @param x	x-location where caret is drawn
+		 * @param y y-location where caret is drawn
+		 * @param w	width of caret
+		 * @param h	height of caret
+		 * @private
+		 */
+		tlf_internal function drawPointSelection(selFormat:SelectionFormat, x:Number,y:Number,w:Number,h:Number):void
+        {
+            var selObj:Shape = new Shape();
+            
+            if (interactionManager.activePosition == interactionManager.anchorPosition)
+				selObj.graphics.beginFill(selFormat.pointColor)
+			else
+				selObj.graphics.beginFill(selFormat.rangeColor);
+				
+			// Oh, this is ugly. If we are in right aligned text, and there is no padding, and the scrollRect is set, 
+			// then in an empty line (or if the point is at the right edge of the line), the blinking cursor is not
+			// visible because it is clipped out. Move it in so we can see it. 
+			if (_hasScrollRect)
+			{
+				if (effectiveBlockProgression == BlockProgression.TB)
+				{
+					if (x >= containerScrollRectRight)
+						x -= w;
+				} 
+				else
+					if (y >= containerScrollRectBottom)
+						y -= h;
+			}
+				
+			selObj.graphics.drawRect(int(x),int(y),w,h);
+			selObj.graphics.endFill();
+			
+			// make it blink
+			if (selFormat.pointBlinkRate != 0 && interactionManager.editingMode == EditingMode.READ_WRITE)
+				startBlinkingCursor(selObj, selFormat.pointBlinkRate);
+
+			addSelectionChild(selObj);
+        }
+        
+        /** Add selection shapes to the displaylist. @private */
+        tlf_internal function addSelectionShapes(selFormat:SelectionFormat, selectionAbsoluteStart:int, selectionAbsoluteEnd:int): void
+		{
+			if (!interactionManager || _textLength == 0 || selectionAbsoluteStart == -1 || selectionAbsoluteEnd == -1)
+				return;
+						
+			var prevLine:TextFlowLine;
+			var nextLine:TextFlowLine;
+			
+			if (selectionAbsoluteStart != selectionAbsoluteEnd)
+			{
+				// adjust selectionAbsoluteStart and selectionAbsoluteEnd to be within this controller
+				var absoluteControllerStart:int = this.absoluteStart;
+				var absoluteControllerEnd:int = this.absoluteStart+this._textLength;
+				
+				if (selectionAbsoluteStart < absoluteControllerStart)
+					selectionAbsoluteStart = absoluteControllerStart;
+				else if (selectionAbsoluteStart >= absoluteControllerEnd)
+					return;	// nothing to do
+					
+				// backup one so that 
+				if (selectionAbsoluteEnd > absoluteControllerEnd)
+					selectionAbsoluteEnd = absoluteControllerEnd;
+				else if (selectionAbsoluteEnd < absoluteControllerStart)
+					return;	// nothing to do
+					
+				CONFIG::debug { assert(selectionAbsoluteStart <= selectionAbsoluteEnd,"addSelectionShapes: bad range"); }
+				CONFIG::debug { assert(selectionAbsoluteStart >= absoluteControllerStart,"addSelectionShapes: bad range"); }
+				CONFIG::debug { assert(selectionAbsoluteEnd <= absoluteControllerEnd,"addSelectionShapes: bad range"); }
+					
+				var begLine:int = flowComposer.findLineIndexAtPosition(selectionAbsoluteStart);
+				var endLine:int = selectionAbsoluteStart == selectionAbsoluteEnd ? begLine : flowComposer.findLineIndexAtPosition(selectionAbsoluteEnd);
+				// watch for going past the end
+				if (endLine >= flowComposer.numLines)
+					endLine = flowComposer.numLines-1;
+					
+				var selObj:Shape = new Shape();
+				prevLine = begLine ? flowComposer.getLineAt(begLine-1) : null;
+				var line:TextFlowLine = flowComposer.getLineAt(begLine); 
+					
+				for (var idx:int = begLine; idx <= endLine; idx++)
+				{
+					nextLine = idx != flowComposer.numLines - 1 ? flowComposer.getLineAt(idx+1) : null;
+						
+					line.hiliteBlockSelection(selObj, selFormat, DisplayObject(this._container),
+						selectionAbsoluteStart < line.absoluteStart ? line.absoluteStart : selectionAbsoluteStart,
+						selectionAbsoluteEnd > line.absoluteStart+line.textLength ? line.absoluteStart+line.textLength : selectionAbsoluteEnd, prevLine, nextLine);
+							
+					var temp:TextFlowLine = line;
+					line = nextLine;
+					prevLine = temp;
+				}
+
+				addSelectionChild(selObj);		
+			}
+			else
+			{
+				var lineIdx:int = flowComposer.findLineIndexAtPosition(selectionAbsoluteStart);
+				// TODO: there is ambiguity - are we at the end of the currentLine or the beginning of the next one?
+				// however must stick to the end of the last line
+				if (lineIdx == flowComposer.numLines)
+					lineIdx--;
+				if (flowComposer.getLineAt(lineIdx).controller == this)
+				{
+					prevLine = lineIdx != 0 ? flowComposer.getLineAt(lineIdx-1) : null;
+					nextLine = lineIdx != flowComposer.numLines-1 ? flowComposer.getLineAt(lineIdx+1) : null
+					flowComposer.getLineAt(lineIdx).hilitePointSelection(selFormat, selectionAbsoluteStart, DisplayObject(this._container), prevLine, nextLine);
+				}
+			}
+		}
+
+		/** Remove all selection shapes. @private */
+		tlf_internal function clearSelectionShapes(): void
+		{
+			stopBlinkingCursor();
+			
+			var selectionSprite:DisplayObjectContainer = getSelectionSprite(false);
+			if (selectionSprite != null)
+			{
+				if (selectionSprite.parent)
+					removeSelectionContainer(selectionSprite);
+				while (selectionSprite.numChildren > 0)
+					selectionSprite.removeChildAt(0);
+				return;
+			}
+		}
+	
+		/** Add a selection child. @private */
+		tlf_internal function addSelectionChild(child:DisplayObject):void
+		{
+			// If there's no selectionSprite on this controller, we use the parent's.
+			// That means we have to translate the coordinates.
+			// TODO: this only supports one level of ntesting
+			var selectionSprite:DisplayObjectContainer = getSelectionSprite(true);
+			
+			if (selectionSprite == null)
+			{
+				return;
+			}
+
+			var selFormat:SelectionFormat = interactionManager.currentSelectionFormat;
+			var curBlendMode:String = (interactionManager.activePosition == interactionManager.anchorPosition) ? selFormat.pointBlendMode : selFormat.rangeBlendMode;
+			var curAlpha:Number = (interactionManager.activePosition == interactionManager.anchorPosition) ? selFormat.pointAlpha : selFormat.rangeAlpha;
+			if (selectionSprite.blendMode != curBlendMode)
+				selectionSprite.blendMode = curBlendMode;
+				
+			if (selectionSprite.alpha != curAlpha)
+				selectionSprite.alpha = curAlpha;
+			
+			if (selectionSprite.numChildren == 0)
+				addSelectionContainer(selectionSprite);
+				
+			selectionSprite.addChild(child);
+		}
+		
+		/** Test for a selection child. @private */
+		tlf_internal function containsSelectionChild(child:DisplayObject):Boolean
+		{ 
+			var selectionSprite:DisplayObjectContainer = getSelectionSprite(false);
+			if (selectionSprite == null)
+			{
+				return false;
+			}
+			return selectionSprite.contains(child); 
+		}
+
+		/** @private */
+		tlf_internal function getBackgroundShape():Shape
+		{
+			if(!_backgroundShape)
+			{
+				_backgroundShape = new Shape();
+				addBackgroundShape(_backgroundShape);
+			}
+			
+			return _backgroundShape;
+		}
+		
+		CONFIG::debug private function containsFloats(textFlow:TextFlow):Boolean
+ 		{
+ 			if (textFlow)
+ 				for (var leaf:FlowLeafElement = textFlow.getFirstLeaf(); leaf != null; leaf = leaf.getNextLeaf())
+ 					if (leaf is InlineGraphicElement && InlineGraphicElement(leaf).float != Float.NONE)
+ 						return true;
+ 			return false;
+		}
+		/**
+		 * @private
+		 */
+		tlf_internal function get effectivePaddingLeft():Number
+		{ return computedFormat.paddingLeft + (_rootElement ? _rootElement.computedFormat.paddingLeft : 0); }
+		/**
+		 * @private
+		 */
+		 tlf_internal function get effectivePaddingRight():Number
+		{ return computedFormat.paddingRight + (_rootElement ? _rootElement.computedFormat.paddingRight : 0); }
+		/**
+		 * @private
+		 */
+		 tlf_internal function get effectivePaddingTop():Number
+		{ return computedFormat.paddingTop + (_rootElement ? _rootElement.computedFormat.paddingTop : 0); }
+		/**
+		 * @private
+		 */
+		 tlf_internal function get effectivePaddingBottom():Number
+		{ return computedFormat.paddingBottom + (_rootElement ? _rootElement.computedFormat.paddingBottom : 0); }
+
+		private var _selectionSprite:Sprite;
+		
+		/** @private */
+		tlf_internal function getSelectionSprite(createIfNull:Boolean):DisplayObjectContainer
+		{
+			if (_selectionSprite == null && createIfNull)
+			{
+				_selectionSprite = new Sprite();
+				_selectionSprite.mouseEnabled = false;
+				_selectionSprite.mouseChildren = false;
+			}
+			return _selectionSprite;
+		}
+		
+		static private function createContainerControllerInitialFormat():ITextLayoutFormat
+		{
+			var ccif:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+			ccif.columnCount = FormatValue.INHERIT;
+			ccif.columnGap = FormatValue.INHERIT;
+			ccif.columnWidth = FormatValue.INHERIT;
+			ccif.verticalAlign = FormatValue.INHERIT;
+			return ccif;
+		}
+		
+		static private var _containerControllerInitialFormat:ITextLayoutFormat = createContainerControllerInitialFormat();
+		
+		/** 
+		* @private
+		* Specifies the initial format (ITextLayoutFormat instance) for a new ContainerController. The runtime
+		* applies this to the format property of all new containers on creation.
+		*
+		* By default, sets the column format values to "inherit"; all other format values are inherited.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.elements.TextFlow TextFlow
+		*/
+		
+		static public function get containerControllerInitialFormat():ITextLayoutFormat
+		{ return _containerControllerInitialFormat; }
+		static public function set containerControllerInitialFormat(val:ITextLayoutFormat):void
+		{ _containerControllerInitialFormat = val; }
+		
+		
+		/** @private */
+		protected function get attachTransparentBackground():Boolean
+		{ return true; }
+		
+		/** @private */
+		tlf_internal function clearCompositionResults():void
+		{
+			setTextLength(0); 
+
+			for each (var textLine:TextLine in _shapeChildren)
+			{
+				removeTextLine(textLine);
+				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",textLine); }
+			}
+			_shapeChildren.length = 0;
+		}
+		
+		/** The TextLines being added to the array in fillShapeChildren are added to tempSprite because they are about to be displayed
+		 * and the TextFlowLine code needs to know that as it keeps all displayed lines in the TextFlowLine textLineCache.  This tells them that.
+		 */
+		static private var tempLineHolder:Sprite = new Sprite();
+		
+		/** Add DisplayObjects that were created by composition to the container. @private */
+		tlf_internal function updateCompositionShapes():void
+		{
+			if(!shapesInvalid)
+			{
+				return;
+			}			
+			
+			// reclamp vertical/horizontal scrollposition - addresses Watson 2380962
+			var scrolled:Boolean = false;	// true if scroll values were changed - we need to notify in this case
+			var tmp:Number = _yScroll;
+			if (verticalScrollPolicy != ScrollPolicy.OFF && !_measureHeight)
+				_yScroll = computeVerticalScrollPosition(_yScroll,false);
+			scrolled = (tmp != _yScroll);
+			tmp = _xScroll;
+			if (horizontalScrollPolicy != ScrollPolicy.OFF && !_measureWidth)
+				_xScroll = computeHorizontalScrollPosition(_xScroll,false);
+			scrolled = scrolled || (tmp != _xScroll);
+
+			// Post all the new TextLines to the display list, and remove any old TextLines left from last time. Do this
+			// in a non-destructive way so that lines that have not been changed are not touched. This reduces redraw time.
+			var newShapeChildren:Array = [ ];
+			fillShapeChildren(newShapeChildren,tempLineHolder);
+			
+			var childIdx:int = getFirstTextLineChildIndex(); // index where the first text line must appear at in its container  
+			var oldIdx:int = 0;		// offset into shapeChildren
+			var newIdx:int = 0;		// offset into newShapeChildren
+
+			while (newIdx != newShapeChildren.length)
+			{
+				var newChild:TextLine = newShapeChildren[newIdx];
+				if (newChild == _shapeChildren[oldIdx])
+				{
+					// Same shape is in both lists, no change necessary, advance to next item in each list
+					childIdx++;
+					newIdx++;
+					oldIdx++;
+					continue;
+				}
+
+				var newChildIdx:int = _shapeChildren.indexOf(newChild);
+				if (newChildIdx == -1)
+				{
+					// Shape is in the new list, but not in the old list, add it to the display list at the current location, and advance to next item
+					addTextLine(newChild, childIdx++);
+					CONFIG::debug { Debugging.traceFTECall(null,_container,"addTextLine",newChild); }
+					newIdx++;
+				}
+				else
+				{
+					// The shape is on both lists, but there are several intervening "old" shapes in between. We'll remove the old shapes that
+					// come before the new one we want to insert.
+					removeAndRecycleTextLines (oldIdx, newChildIdx);
+					oldIdx = newChildIdx;
+				}
+			}
+
+			// remove any trailing children no longer displayed
+			removeAndRecycleTextLines (oldIdx, _shapeChildren.length);
+
+			_shapeChildren = newShapeChildren;
+			shapesInvalid = false;
+									
+			// TODO: support for inline children (tables)
+			// synchronize the inline shapes beginning at childIdx 
+			updateInlineChildren();
+			
+			// _textFrame.updateVisibleRectangle(this._visibleRect);
+			updateVisibleRectangle();
+			
+			// If we're measuring, then the measurement values may have changed since last time.
+			// Force the transparent background to redraw, so that mouse events will work for the 
+			// entire content area.
+			if (_measureWidth || _measureHeight)
+				attachTransparentBackgroundForHit(false);
+			
+			var tf:TextFlow = this.textFlow;
+			if (tf.backgroundManager)
+			{
+				tf.backgroundManager.onUpdateComplete(this);
+			}
+			
+			// If we updated the scroll values, we need to send an event
+			if (scrolled && tf.hasEventListener(TextLayoutEvent.SCROLL))
+			{
+				tf.dispatchEvent(new TextLayoutEvent(TextLayoutEvent.SCROLL));
+			}
+
+			if (tf.hasEventListener(UpdateCompleteEvent.UPDATE_COMPLETE))
+			{
+				tf.dispatchEvent(new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE,false,false,tf, this));
+			}
+			
+			CONFIG::debug { assert(tempLineHolder.numChildren == 0,"Uh oh"); }
+			CONFIG::debug { validateLines(); }
+			// prevent leaks here - this code should't be needed
+			while (tempLineHolder.numChildren)
+				tempLineHolder.removeChildAt(0);
+		}
+		
+		private function removeAndRecycleTextLines (beginIndex:int, endIndex:int):void
+		{
+			var backgroundManager:BackgroundManager = textFlow.backgroundManager;
+			
+			var child:TextLine;
+			while (beginIndex < endIndex)
+			{
+				child = _shapeChildren[beginIndex++];
+				
+				removeTextLine(child);
+				CONFIG::debug { Debugging.traceFTECall(null,_container,"removeTextLine",child); }
+				
+				// Recycle if its not displayed and not connected to the textblock
+				if (TextLineRecycler.textLineRecyclerEnabled && !child.parent)
+				{
+					if (child.userData == null)
+					{
+						TextLineRecycler.addLineForReuse(child);
+						if (backgroundManager)
+							backgroundManager.removeLineFromCache(child);
+					}
+					else if (child.validity == TextLineValidity.INVALID)
+					{
+						if (child.nextLine == null && child.previousLine == null && (!child.textBlock || child.textBlock.firstLine != child))
+						{
+							child.userData.releaseTextLine();
+							child.userData = null;
+							TextLineRecycler.addLineForReuse(child);
+							if (backgroundManager)
+								backgroundManager.removeLineFromCache(child);
+						}
+					}
+				}
+			}
+		} 
+		
+		/**
+		 * Gets the index at which the first text line must appear in its parent.
+		 * The default implementation of this method, which may be overriden, returns the child index 
+		 * of the first <code>flash.text.engine.TextLine</code> child of <code>container</code>
+		 * if one exists, and that of the last child of <code>container</code> otherwise. 
+		 * 
+		 * @return the index at which the first text line must appear in its parent.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.text.engine.TextLine
+		 * @see #container
+		 */	
+		protected function getFirstTextLineChildIndex():int
+		{			
+			// skip past any non-TextLine children below the text in the container,
+			// This also means that in a container devoid of text, we will always
+			// populate the text starting at index container.numChildren, which is intentional.
+			var firstTextLine:int;
+			for(firstTextLine = 0; firstTextLine<_container.numChildren; ++firstTextLine)
+			{
+				if(_container.getChildAt(firstTextLine) is TextLine)
+				{
+					break;
+				}
+			}
+			return firstTextLine;
+		}
+			 
+		/**
+		 * Adds a <code>flash.text.engine.TextLine</code> object as a descendant of <code>container</code>.
+		 * The default implementation of this method, which may be overriden, adds the object
+		 * as a direct child of <code>container</code> at the specified index.
+		 * 
+		 * @param textLine the <code>flash.text.engine.TextLine</code> object to add
+		 * @param index insertion index of the text line in its parent 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.text.engine.TextLine
+		 * @see #container
+		 * 
+		 */	
+		protected function addTextLine(textLine:TextLine, index:int):void
+		{
+			_container.addChildAt(textLine, index);
+		}
+		
+		/**
+		 * Removes a <code>flash.text.engine.TextLine</code> object from its parent. 
+		 * The default implementation of this method, which may be overriden, removes the object
+		 * from <code>container</code> if it is a direct child of the latter.
+		 * 
+		 * This method may be called even if the object is not a descendant of <code>container</code>.
+		 * Any implementation of this method must ensure that no action is taken in this case.
+		 * 
+		 * @param textLine the <code>flash.text.engine.TextLine</code> object to remove 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.text.engine.TextLine
+		 * @see #container
+		 * 
+		 */	
+		protected function removeTextLine(textLine:TextLine):void
+		{
+			if (_container.contains(textLine))
+  				_container.removeChild(textLine);
+		}
+
+		/**
+		 * Adds a <code>flash.display.Shape</code> object on which background shapes (such as background color) are drawn.
+		 * The default implementation of this method, which may be overriden, adds the object to <code>container</code>
+		 * just before the first <code>flash.text.engine.TextLine</code> child, if one exists, and after the last exisiting
+		 * child otherwise. 
+		 * 
+		 * @param shape <code>flash.display.Shape</code> object to add
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.display.Shape
+		 * @see flash.text.engine.TextLine
+		 * @see #container
+		 * 
+		 */
+		protected function addBackgroundShape(shape:Shape):void
+		{
+			_container.addChildAt(_backgroundShape, getFirstTextLineChildIndex());
+		}
+		
+		/**
+		 * Adds a <code>flash.display.DisplayObjectContainer</code> object to which selection shapes (such as block selection highlight, cursor etc.) are added.
+		 * The default implementation of this method, which may be overriden, has the following behavior:
+		 * The object is added just before first <code>flash.text.engine.TextLine</code> child of <code>container</code> if one exists 
+		 * and the object is opaque and has normal blend mode. 
+		 * In all other cases, it is added as the last child of <code>container</code>.
+		 * 
+		 * @param selectionContainer <code>flash.display.DisplayObjectContainer</code> object to add
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.display.DisplayObjectContainer
+		 * @see flash.text.engine.TextLine
+		 * @see #container
+		 */
+		protected function addSelectionContainer(selectionContainer:DisplayObjectContainer):void
+		{
+			if (selectionContainer.blendMode == BlendMode.NORMAL && selectionContainer.alpha == 1)
+			{
+				// don't put selection behind background color or existing content in container, put it behind first text line
+				_container.addChildAt(selectionContainer, getFirstTextLineChildIndex());
+			}
+			else
+				_container.addChild(selectionContainer);
+		}
+		
+		/**
+		 * Removes the <code>flash.display.DisplayObjectContainer</code> object which contains selection shapes (such as block selection highlight, cursor etc.).
+		 * The default implementation of this method, which may be overriden, removes the object from its parent if one exists.
+		 * 
+		 * @param selectionContainer <code>flash.display.DisplayObjectContainer</code> object to remove
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flash.display.DisplayObjectContainer
+		 * @see #container
+		 * 
+		 */
+		protected function removeSelectionContainer(selectionContainer:DisplayObjectContainer):void
+		{	
+			selectionContainer.parent.removeChild(selectionContainer);
+		}
+		
+		/**
+		 * @private
+		 */
+		tlf_internal function get textLines():Array
+		{
+			return _shapeChildren;
+		}
+		
+		/** 
+		 * If scrolling, sets the scroll rectangle to the container rectangle so that any lines that are 
+		 * halfway in view are clipped to the scrollable region. If not scrolling, clear the
+		 * scroll rectangle so that no clipping occurs.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		protected function updateVisibleRectangle() :void
+		{
+			if (horizontalScrollPolicy == ScrollPolicy.OFF && verticalScrollPolicy == ScrollPolicy.OFF)
+			{
+				if (_hasScrollRect)
+				{
+					_container.scrollRect = null;
+					_hasScrollRect = false;
+					
+				}
+			}
+			else
+			{
+				var contentRight:Number = _contentLeft+contentWidth;
+				var contentBottom:Number = _contentTop+contentHeight;
+				var width:Number;
+				var compositionRight:Number;
+				if (_measureWidth)
+				{
+					width = contentWidth;
+					compositionRight = _contentLeft + width
+				}
+				else
+				{
+					width = _compositionWidth;
+					compositionRight = width;
+				}
+				var height:Number;
+				var compositionBottom:Number;
+				if (_measureHeight)
+				{
+					height = contentHeight;
+					compositionBottom = _contentTop + height;
+				}
+				else
+				{
+					height = _compositionHeight;
+					compositionBottom = height;
+				}
+				var xOrigin:Number = (effectiveBlockProgression == BlockProgression.RL) ? -width : 0;
+				var xpos:int = horizontalScrollPosition + xOrigin;
+				var ypos:int = verticalScrollPosition;
+				
+				if (textLength == 0 || xpos == 0 && ypos == 0 && _contentLeft >= xOrigin && _contentTop >= 0 && contentRight <= compositionRight && contentBottom <= compositionBottom)
+				{
+					if(_hasScrollRect)
+					{
+						_container.scrollRect = null;
+						CONFIG::debug { Debugging.traceFTECall(null,_container,"clearContainerScrollRect()"); }
+						_hasScrollRect = false;
+					}
+				}
+				else 
+				{
+					// don't look at hasScrollRect but do look at scrollRect - client may have messed with it; okay to touch it because about to set it
+					var rect:Rectangle = _container.scrollRect;
+					if (!rect || rect.x != xpos || rect.y != ypos || rect.width != width || rect.height != height)
+					{
+						_container.scrollRect = new Rectangle(xpos, ypos, width, height);
+						CONFIG::debug { Debugging.traceFTECall(null,_container,"setContainerScrollRect",xpos, ypos, width, height); }
+						_hasScrollRect = true;
+					}
+				}
+			}
+			
+			//Fix for Watson 2347938 - re-add the transparent background as the dimension of the
+			//container are altered by sutting down the scrolls in vertical text.
+			this.attachTransparentBackgroundForHit(false);
+		}
+		
+		include "../formats/TextLayoutFormatInc.as";
+		
+		/** 
+		 * The <code>userStyles</code> object for a ContainerController instance.  The getter makes a copy of the 
+		 * <code>userStyles</code> object, which is an array of <em>stylename-value</em> pairs.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function get userStyles():Object
+		{
+			var styles:Object = _formatValueHolder == null ? null : _formatValueHolder.userStyles;
+			return styles ? Property.shallowCopy(styles) : null;
+		}
+		public function set userStyles(styles:Object):void
+		{
+			var newStyles:Object = new Object();
+			for (var val:Object in styles)
+				newStyles[val] = styles[val];
+			writableTextLayoutFormatValueHolder().userStyles = newStyles;
+			formatChanged(); // modelChanged(ModelChange.USER_STYLE_CHANGED,0,this.textLength,true);
+		}
+
+		/** Returns the <code>coreStyles</code> on this ContainerController.  Note that the getter makes a copy of the core 
+		 * styles dictionary. The coreStyles object encapsulates those formats that are defined by TextLayoutFormat. The
+		 * <code>coreStyles</code> object consists of an array of <em>stylename-value</em> pairs.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function get coreStyles():Object
+		{
+			var styles:Object = _formatValueHolder == null ? null : _formatValueHolder.coreStyles;
+			return styles ? Property.shallowCopy(styles) : null;
+		}		
+		
+		/** 
+		 * Stores the ITextLayoutFormat object that contains the attributes for this container. 
+		 * The controller inherits the container properties from the TextFlow of which it is part. 
+		 * This property allows different controllers in the same text flow to have, for example, 
+		 * different column settings or padding.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.formats.ITextLayoutFormat
+	 	 */
+		public function get format():ITextLayoutFormat
+		{ return _formatValueHolder; }
+		public function set format(value:ITextLayoutFormat):void
+		{
+			formatInternal = value;
+			formatChanged();
+		}
+		
+		private function writableTextLayoutFormatValueHolder():FlowValueHolder
+		{
+			if (_formatValueHolder == null)
+				_formatValueHolder = new FlowValueHolder();
+			return _formatValueHolder;
+		}
+
+		/** Sets the _format data member. No side effects.
+		 * @private
+		 */
+		tlf_internal function set formatInternal(value:ITextLayoutFormat):void
+		{	
+			if (value == null)
+			{
+				if (_formatValueHolder == null || _formatValueHolder.coreStyles == null)
+					return; // no change
+				_formatValueHolder.coreStyles = null;
+			}
+			else
+				writableTextLayoutFormatValueHolder().format = value;
+		}
+
+		/** Returns the value of the style specified by the <code>styleProp</code> parameter.
+		 *
+		 * @param styleProp The name of the style property whose value you want.
+		 *
+		 * @return	The current value for the specified style.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function getStyle(styleProp:String):*
+		{
+			if (TextLayoutFormat.description.hasOwnProperty(styleProp))
+				return computedFormat[styleProp];
+			return getUserStyleWorker(styleProp);
+		}
+		
+		/** 
+		* Sets the value of the style specified by the <code>styleProp</code> parameter to the value
+		* specified by the <code>newValue</code> parameter.
+		*
+		* @param styleProp The name of the style property whose value you want to set.
+		* @param newValue The value that you want to assign to the style.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function setStyle(styleProp:String,newValue:*):void
+		{
+			if (TextLayoutFormat.description[styleProp] !== undefined)
+				this[styleProp] = newValue;
+			else
+			{
+				_formatValueHolder.setUserStyle(styleProp,newValue);
+				formatChanged(); // modelChanged(ModelChange.USER_STYLE_CHANGED,0,this.textLength,true);
+			}
+		}
+		
+		/** Clears the style specified by <code>styleProp</code> from this FlowElement. Sets the value to
+		 * <code>undefined</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function clearStyle(styleProp:String):void
+		{ setStyle(styleProp,undefined); }
+		
+		/** @private worker function - any styleProp */
+		tlf_internal function getUserStyleWorker(styleProp:String):*
+		{
+			CONFIG::debug { assert(TextLayoutFormat.description[styleProp] === undefined,"bad call to getUserStyleWorker"); }
+				
+			var userStyle:* = _formatValueHolder.getUserStyle(styleProp)
+			if (userStyle !== undefined)
+				return userStyle;
+				
+			var tf:TextFlow = _rootElement ? _rootElement.getTextFlow() : null;
+			if (tf && tf.formatResolver)
+			{
+				userStyle = tf.formatResolver.resolveUserFormat(this,styleProp);
+				if (userStyle !== undefined)
+					return userStyle;
+			}
+			// or should it go to the container?
+			return _rootElement ? _rootElement.getUserStyleWorker(styleProp) : undefined;
+		}
+		
+		/** 
+		 * Returns an ITextLayoutFormat instance with the attributes applied to this container, including the attributes inherited from its
+   		 * root element.
+		 * 
+		 * @return 	object that describes the container's attributes.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #rootElement
+	 	 */
+		public function get computedFormat():ITextLayoutFormat
+		{
+			if (!_computedFormat)
+			{
+				FlowElement._scratchTextLayoutFormat.format = formatForCascade;
+				var element:FlowElement = _rootElement;
+				if (element)
+				{
+					while (1)
+					{
+						var attrs:ITextLayoutFormat = ContainerFormattedElement(element).formatForCascade;
+						if (attrs)
+							FlowElement._scratchTextLayoutFormat.concatInheritOnly(attrs);
+						if (element.parent == null)
+							break;
+						element = element.parent;
+					}
+				}
+				var defaultFormat:ITextLayoutFormat;
+				var defaultFormatHash:uint;
+				var tf:TextFlow = element as TextFlow;
+				if (tf)
+				{
+					defaultFormat = tf.getDefaultFormat();
+					defaultFormatHash = tf.getDefaultFormatHash();
+				}
+				_computedFormat= TextFlow.getCanonical(FlowElement._scratchTextLayoutFormat,defaultFormat,defaultFormatHash);
+				
+				resetColumnState();
+			}
+			return _computedFormat;
+		}
+		
+		/** @private */
+		tlf_internal function get formatForCascade():ITextLayoutFormat
+		{
+			if (_rootElement)
+			{
+				var tf:TextFlow = _rootElement.getTextFlow();
+				if (tf)
+				{
+					var elemStyle:ITextLayoutFormat  = tf.getTextLayoutFormatStyle(this);
+					if (elemStyle)
+					{
+						var localFormat:ITextLayoutFormat = format;
+						if (localFormat == null)
+							return elemStyle;
+							
+						var rslt:TextLayoutFormat = new TextLayoutFormat(elemStyle);
+						rslt.apply(localFormat);
+						return rslt;
+					}
+				}
+			}
+			return format;
+		}
+		
+		/** @private */
+		tlf_internal function getPlacedTextLineBounds(textLine:TextLine):Rectangle
+		{
+			var curBounds:Rectangle;
+			if (!textLine.parent)
+			{
+				// Has to be in the container to get the bounds
+				addTextLine(textLine,0);
+				curBounds = textLine.getBounds(_container);
+				removeTextLine(textLine);
+			}
+			else
+			{
+				// Note: Relative to its parent, which may not be _container
+				// but in all reasonable cases, should share its origin with _container -- really???
+				curBounds = textLine.getBounds(textLine.parent);
+			}
+				
+			return curBounds;
+		}
+			
+		/** @private */
+		tlf_internal function getInteractionHandler():IInteractionEventHandler
+		{ return this; }
+	}
+
+}
+import flash.events.MouseEvent;
+import flash.display.InteractiveObject;
+	
+class PsuedoMouseEvent extends MouseEvent
+{
+	public function PsuedoMouseEvent(type:String, bubbles:Boolean = true, cancelable:Boolean = false, localX:Number = NaN, localY:Number = NaN, relatedObject:InteractiveObject = null, ctrlKey:Boolean = false, altKey:Boolean = false, shiftKey:Boolean = false, buttonDown:Boolean = false)
+	{
+		super(type,bubbles,cancelable,localX,localY,relatedObject,ctrlKey,altKey,shiftKey,buttonDown);
+	}
+	public override function get currentTarget():Object
+	{ return relatedObject; }
+	public override function get target():Object
+	{ return relatedObject; }
+}
diff --git a/textLayout_core/src/flashx/textLayout/container/ISandboxSupport.as b/textLayout_core/src/flashx/textLayout/container/ISandboxSupport.as
new file mode 100755
index 0000000..87394c2
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/container/ISandboxSupport.as
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+	import flash.events.Event;
+	/** Interface to support TLF content in a sub-application. When an application is loaded in an untrusted context,
+	 * mouse events that occur outside of the untrusted application's bounds are not delivered. Clients can handle this
+	 * by implementing ISandboxSupport. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 * 
+	 * @see flashx.textLayout.container.ContainerController
+	 * @see flashx.textLayout.container.TextContainerManager
+	 * @see flashx.textLayout.edit.SelectionManager
+	 * @see flash.system.SecurityDomain
+	 */
+	public interface ISandboxSupport
+	{
+		/** 
+		 * Called to request clients to begin the forwarding of mouseup and mousemove events from outside a security sandbox.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		function beginMouseCapture():void;
+		/** 
+		 * Called to inform clients that the the forwarding of mouseup and mousemove events from outside a security sandbox is no longer needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		function endMouseCapture():void;
+		/** Client call to forward a mouseUp event from outside a security sandbox.  Coordinates of the mouse up are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		function mouseUpSomewhere(event:Event):void;
+		/** Client call to forward a mouseMove event from outside a security sandbox.  Coordinates of the mouse move are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		function mouseMoveSomewhere(event:Event):void;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/container/ScrollPolicy.as b/textLayout_core/src/flashx/textLayout/container/ScrollPolicy.as
new file mode 100755
index 0000000..462455d
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/container/ScrollPolicy.as
@@ -0,0 +1,83 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+	import flashx.textLayout.property.EnumStringProperty;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	/**
+	 *  The ScrollPolicy class is an enumeration class that defines values for setting the <code>horizontalScrollPolicy</code> and 
+	 *  <code>verticalScrollPolicy</code> properties of the ContainerController class, which defines a text flow 
+	 *  container. 
+	 *
+	 *  @see ContainerController#horizontalScrollPolicy
+	 *  @see ContainerController#verticalScrollPolicy
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class ScrollPolicy
+	{
+		/** 
+		 * Specifies that scrolling is to occur if the content exceeds the container's dimension. The runtime calculates 
+		 * the number of lines that overflow the container and the user can navigate to them with cursor keys, by drag selecting,
+		 * or by rotating the mouse wheel. You can also cause scrolling to occur by setting the corresponding position value, 
+		 * either <code>ContainerController.horizontalScrollPosition</code> or <code>ContainerController.verticalScrollPosition</code>. Also, the runtime can automatically 
+		 * scroll the contents of the container during editing.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const AUTO:String = "auto";
+		
+		/** 
+		 * Causes the runtime to not display overflow lines, which means that the user cannot navigate to them. 
+		 * In this case, setting the corresponding <code>ContainerController.horizontalScrollPosition</code> and 
+		 * <code>ContainerController.verticalScrollPosition</code> properties have no effect. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const OFF:String = "off";
+		
+		/** 
+		 * Specifies that scrolling is available to access content that exceeds the container's dimension. The runtime calculates the 
+		 * number of lines that overflow the container and allows the user to scroll them into view with the cursor keys, by drag selecting, 
+		 * or by rotating the mouse wheel. You can also scroll by setting the corresponding position value, either 
+		 * <code>ContainerController.horizontalScrollPosition</code> or <code>ContainerController.verticalScrollPosition</code>. Also, the runtime can automatically scroll the contents 
+		 * of the container during editing.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const ON:String = "on";		
+		
+		/** Shared definition of the scrollPolicy property. @private */
+		static tlf_internal const scrollPolicyPropertyDefinition:EnumStringProperty = new EnumStringProperty("scrollPolicy", ScrollPolicy.AUTO, false, null, 
+			ScrollPolicy.AUTO, ScrollPolicy.OFF, ScrollPolicy.ON);	
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/debug/Debugging.as b/textLayout_core/src/flashx/textLayout/debug/Debugging.as
new file mode 100755
index 0000000..6548256
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/debug/Debugging.as
@@ -0,0 +1,206 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.debug 
+{
+	[ExcludeClass]
+	/** @private */
+	public class Debugging 
+	{
+		import flash.utils.Dictionary;
+		import flashx.textLayout.tlf_internal;
+		
+		use namespace tlf_internal;
+		
+		CONFIG::debug 
+		{
+			static tlf_internal var debugOn:Boolean = true;
+			static tlf_internal var traceFlag:Boolean = false;	
+			static tlf_internal var verbose:Boolean = false;	
+			static tlf_internal var throwOnAssert:Boolean = false;
+			static tlf_internal var containerLineValidation:Boolean = false;
+			
+			static private var traceOutString:String;
+			static private var traceChanged:Function = null;
+			
+			
+			static public function traceOut(str:String, ...rest):void
+			{
+				if (!traceOutString)
+					traceOutString = new String();
+				for each (var obj:Object in rest)
+				{
+					str += obj.toString();
+					str += " ";
+				}
+
+				traceOutString += str + "\n";
+				if (traceChanged != null)
+					traceChanged(traceOutString);
+				else
+					trace(str);
+			}
+			
+			static public function setTraceChanged(listener:Function):void
+			{
+				traceChanged = listener;
+			}
+
+			// ///////////////////////////////
+			// support creating a log of calls 
+			// //////////////////////////////
+			
+			static tlf_internal var generateDebugTrace:Boolean = false;
+			static private var idDictionary:Dictionary = new Dictionary(true);
+			static private var nextKey:int = 1;
+			static private var callCount:int = 1;
+		
+			static private const vectPrefix:String = "__AS3__.vec::Vector";
+			static private function getClassForIdentity(o:Object):String
+			{
+				var s:String = flash.utils.getQualifiedClassName(o);
+				if (s.substr(0,vectPrefix.length) == vectPrefix)
+				{
+					s = s.substr( s.lastIndexOf(":")+1);
+					return "VectorOf" + s.substr(0,s.length-1);
+				}
+				return s.substr( s.lastIndexOf(":")+1);
+			}
+			
+			static tlf_internal function getIdentity(o:Object):String
+			{
+				if (idDictionary[o] == null)
+				{
+					var s:String = getClassForIdentity(o);
+					idDictionary[o] = "my" + s + nextKey.toString();
+					nextKey++;
+				}
+				return idDictionary[o];
+			}
+			
+			static tlf_internal function getClassForType(o:Object):String
+			{
+				var s:String = flash.utils.getQualifiedClassName(o);
+				if (s.substr(0,vectPrefix.length) == vectPrefix)
+				{
+					s = s.substr( s.lastIndexOf(":")+1);
+					return "Vector.<" + s ;
+				}
+				return s.substr( s.lastIndexOf(":")+1);
+			}
+			
+			static tlf_internal function makeParameter(obj:Object):String
+			{
+				var str:String;
+				if (obj == null)
+					str = "null"
+				else if (obj is String)
+				{
+					var tempString:String = String(obj);
+					var idx:int;
+					
+					// any out of bounds characters?
+					var allokay:Boolean = true;
+					for (idx = 0; idx < tempString.length; idx++)
+					{
+						if (tempString.charCodeAt(idx) > 0xFF)
+						{
+							allokay = false;
+							break;
+						}
+					}
+					if (allokay)
+						str = "\"" + tempString +  "\"";
+					else
+					{
+						str = "String.fromCharCode("
+						for (idx = 0; idx < tempString.length; idx++)
+						{
+							if (idx != 0)
+								str += ", ";
+							str += "0x" + tempString.charCodeAt(idx).toString(16);
+						}
+						str += ")";
+					}
+				}
+				else if (obj is Number || obj is int)
+					str = obj.toString();
+				else if (obj is Boolean)
+					str = Boolean(obj) ? "true" : "false";
+				else 
+					str = getIdentity(obj);
+				return str;
+			}
+			
+			/** @private Trace a function call */
+			static tlf_internal function traceFTECall(rslt:Object,target:Object,method:String,...rest):void
+			{
+				if (!generateDebugTrace)
+					return;
+					
+				// if result already exists then null it out - its a side effect
+				if (idDictionary[rslt] != null)
+					rslt = null;
+				var str:String = "	";
+				var rsltType:String;
+				if (rslt)
+				{
+					rsltType = getClassForType(rslt);
+					str += "var " + getIdentity(rslt) + ":" + getClassForType(rslt) + " = ";
+				}
+				
+				if (target)
+					str += getIdentity(target) + ".";
+				
+				if (rest.length == 0)
+				{
+					str += method + ";";
+				}
+				else
+				{
+					str += method + "(";
+					for (var i:int =0; i<rest.length; i++)
+					{
+						if (i != 0)
+							str += ","
+						str += makeParameter(rest[i]);
+					}
+	
+					if (rslt)
+						str += ") as " + rsltType + ";"; 
+					else
+						str += ");"
+				}
+				str += " // " + callCount.toString();
+				trace(str);
+				callCount++;
+			}
+			
+			/** @private Trace a property assignment */
+			static tlf_internal function traceFTEAssign(target:Object,prop:String,val:Object):void
+			{
+				if (!generateDebugTrace)
+					return;
+					
+				var str:String = "	" + getIdentity(target) + "." + prop + " = " + makeParameter(val) + ";" +  "// " + callCount.toString();
+				trace(str);
+				callCount++;
+			}
+		}
+	}
+} // end package
diff --git a/textLayout_core/src/flashx/textLayout/debug/assert.as b/textLayout_core/src/flashx/textLayout/debug/assert.as
new file mode 100755
index 0000000..4aa2738
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/debug/assert.as
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.debug 
+{
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+
+	/** @private
+	 *  Debug only function that prints a trace message if condition is false.
+	 *  @return count of errors reported this assert: 1 or 0.
+	 * */
+	CONFIG::debug public function assert(condition:Boolean, warning:String):int
+	{
+		if (!condition)
+		{
+			trace("ERROR: " + warning);
+			// throw if the bit is set
+			if (Debugging.throwOnAssert)
+				throw(new Error("TextLayoutAssert: " + warning));
+			return 1;
+		}
+		return 0;
+	}
+	/** @private */
+	CONFIG::release 
+	public function assert():void 
+	{
+	} 
+} // end package
diff --git a/textLayout_core/src/flashx/textLayout/edit/EditingMode.as b/textLayout_core/src/flashx/textLayout/edit/EditingMode.as
new file mode 100755
index 0000000..34eaeb6
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/edit/EditingMode.as
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	/** 
+	 * The EditingMode class defines constants used with EditManager class to represent the 
+	 * read, select, and edit permissions of a document.
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public final class EditingMode
+	{
+		/** 
+		 * The document is read-only.
+		 * 
+		 * <p>Neither selection nor editing is allowed.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public static const READ_ONLY:String = "readOnly";
+		/** 
+		 * The document can be edited.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public static const READ_WRITE:String = "readWrite";
+		/** 
+		 * The text in the document can be selected and copied, but not edited. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public static const READ_SELECT:String = "readSelect";			
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/edit/IInteractionEventHandler.as b/textLayout_core/src/flashx/textLayout/edit/IInteractionEventHandler.as
new file mode 100755
index 0000000..b9c558e
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/edit/IInteractionEventHandler.as
@@ -0,0 +1,212 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.IMEEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.TextEvent;
+	
+	/**
+	 * The IInteractionEventHandler interface defines the event handler functions that
+	 * are handled by a Text Layout Framework selection or edit manager.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface IInteractionEventHandler
+	{
+		/** 
+		 * Processes an edit event.
+		 * 
+		 * <p>Edit events are dispatched for cut, copy, paste, and selectAll commands.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function editHandler(event:Event):void;
+		
+		/** 
+		* Processes a keyDown event.
+		*  
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/	
+		function keyDownHandler(event:KeyboardEvent):void;
+		
+		/** 
+		* Processes a keyUp event.
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/	
+		function keyUpHandler(event:KeyboardEvent):void;		
+		
+		/** 
+		* Processes a keyFocusChange event.
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/	
+		function keyFocusChangeHandler(event:FocusEvent):void;
+		
+		/** 
+		 * Processes a TextEvent.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function textInputHandler(event:TextEvent):void;
+
+		/** 
+		 * Processes an imeStartComposition event
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function imeStartCompositionHandler(event:IMEEvent):void;
+		
+		/** 
+		 * Processes a mouseDown event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function mouseDownHandler(event:MouseEvent):void;
+
+		/** 
+		 * Processes a mouseMove event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function mouseMoveHandler(event:MouseEvent):void;
+		
+		/** 
+		 * Processes a mouseUp event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function mouseUpHandler(event:MouseEvent):void;		
+		
+		/** 
+		 * Processes a mouseDoubleClick event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function mouseDoubleClickHandler(event:MouseEvent):void;
+
+		/** 
+		 * Processes a mouseOver event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */			
+		function mouseOverHandler(event:MouseEvent):void;
+
+		/** 
+		 * Processes a mouseOut event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */					
+		function mouseOutHandler(event:MouseEvent):void;
+		
+		/** 
+		 * Processes a focusIn event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function focusInHandler(event:FocusEvent):void;
+		 
+		/** 
+		 * Processes a focusOut event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function focusOutHandler(event:FocusEvent):void;
+
+		/** 
+		 * Processes an activate event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */				
+		function activateHandler(event:Event):void;
+		
+		/** 
+		 * Processes a deactivate event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */				
+		function deactivateHandler(event:Event):void;
+		
+		/** 
+		 * Processes a focusChange event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */				
+		function focusChangeHandler(event:FocusEvent):void
+		
+		/** 
+		 * Processes a menuSelect event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */				
+		function menuSelectHandler(event:ContextMenuEvent):void
+		
+		/** 
+		 * Processes a mouseWheel event.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */				
+		function mouseWheelHandler(event:MouseEvent):void
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/edit/ISelectionManager.as b/textLayout_core/src/flashx/textLayout/edit/ISelectionManager.as
new file mode 100755
index 0000000..debf89f
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/edit/ISelectionManager.as
@@ -0,0 +1,384 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.display.InteractiveObject;
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.TextEvent;
+	
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.elements.TextRange;
+
+	/** 
+	 * The ISelectionManager interface defines the interface for handling text selection.
+	 * 
+	 * <p>A SelectionManager keeps track of the selected text range and handles events for a TextFlow.</p>
+	 * 
+	 * <p>A selection can be either a point selection or a range selection. A point selection is the insertion point
+	 * and is indicated visually by drawing a cursor. A range
+	 * selection includes the text between an anchor point and an active point.</p>
+	 * 
+	 * @see flashx.textLayout.edit.SelectionManager
+	 * @see flashx.textLayout.edit.TextScrap
+	 * @see flashx.textLayout.elements.TextFlow
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public interface ISelectionManager extends IInteractionEventHandler
+	{		
+		/** 
+		 * The TextFlow object managed by this selection manager. 
+		 * 
+		 * <p>A selection manager manages a single text flow. A selection manager can also be
+		 * assigned to a text flow by setting the <code>interactionManager</code> property of the
+		 * TextFlow object.</p>
+		 * 
+		 * @see flashx.textLayout.elements.TextFlow#interactionManager
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get textFlow():TextFlow;
+		function set textFlow(flow:TextFlow):void;
+		
+		/** 
+		 * The text position of the start of the selection, as an offset from the start of the text flow.
+		 *  
+		 * <p>The absolute start is the same as either the active or the anchor point of the selection, whichever comes
+		 * first in the text flow.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get absoluteStart() : int;
+		/** 
+		 * The text position of the end of the selection, as an offset from the start of the text flow.
+		 *  
+		 * <p>The absolute end is the same as either the active or the anchor point of the selection, whichever comes
+		 * last in the text flow.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get absoluteEnd() : int;
+
+		/**
+		 * Selects a range of text.
+		 * 
+		 * <p>If a negative number is passed as either of the parameters, then any existing selection is
+		 * removed.</p>
+		 * 
+		 * @param anchorPosition	The anchor point for the new selection, as an absolute position in the TextFlow 
+		 * @param activePosition	The active end of the new selection, as an absolute position in the TextFlow
+		 * 
+		 * @includeExample examples\SelectionManager_setSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function selectRange(anchorPosition:int, activePosition:int) : void
+		
+		/**
+		 * Selects the entire flow
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function selectAll() : void
+		
+		/** 
+		 * The anchor point of the selection. 
+		 * 
+		 * <p>An <em>anchor</em> point is the stable end of the selection. When the selection
+		 * is extended, the anchor point does not change. The anchor point can be at either the beginning 
+		 * or the end of the selection.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */								
+		function get anchorPosition() : int;
+
+		/** 
+		 * The active point of the selection.
+		 * 
+		 * <p>The <em>active</em> point is the volatile end of the selection. The active point is changed 
+		 * when the selection is modified. The active point can be at either the beginning 
+		 * or the end of the selection.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */										
+		function get activePosition() : int;
+		
+		/**
+		 * Indicates whether there is a selection. 
+		 * 
+		 * <p>Returns <code>true</code> if there is either a range selection or a point selection. 
+		 * By default, when a selection manager is first set up, there is no selection (the start and end are -1).</p>
+		 * 
+		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function hasSelection():Boolean;
+		
+		/**
+		 * Indicates whether the selection covers a range of text.
+		 * 
+		 * <p>Returns <code>true</code> if there is a selection that extends past a single position.</p> 
+		 * 
+		 * @includeExample examples\SelectionManager_isRangeSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function isRangeSelection():Boolean;
+		
+		/**
+		 * Gets the SelectionState object of the current selection.
+		 * 
+		 * @includeExample examples\SelectionManager_getSelectionState.as -noswf
+		 * 
+		 * @see flashx.textLayout.edit.SelectionState
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function getSelectionState():SelectionState;
+		
+		/**
+		 * Sets the SelectionState object of the current selection.
+		 * 
+		 * @see flashx.textLayout.edit.SelectionState
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function setSelectionState(state:SelectionState):void;
+
+		/** 
+		 * Redisplays the selection shapes. 
+		 * 
+		 * <p><b>Note:</b> You do not need to call this method directly. It is called automatically.</p>	
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		function refreshSelection():void;
+
+
+		/** 
+		 * Gives the focus to the first container in the selection.
+		 *  
+		 * @includeExample examples\SelectionManager_setFocus.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+ 		 */
+		function setFocus():void;
+		
+		/** 
+		 * Indicates whether a container in the text flow has the focus.
+		 * 
+		 * <p>The <code>focused</code> property is <code>true</code> 
+		 * if any of the containers in the text flow has key focus.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get focused():Boolean;
+		
+		/** 
+		 * Indicates whether the window associated with the text flow is active.
+		 * 
+		 * <p>The <code>windowActive</code> property is <code>true</code> if the window 
+		 * displaying with the text flow is the active window.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get windowActive():Boolean;
+		
+		/** 
+		 * The current SelectionFormat object.
+		 * 
+		 * <p>The current SelectionFormat object is chosen from the SelectionFormat objects assigned to the 
+		 * <code>unfocusedSelectionFormat</code>, <code>inactiveSelectionFormat</code> and <code>focusedSelectionFormat</code> 
+		 * properties based on the current state of the <code>windowActive</code> and <code>focused</code> properties.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function get currentSelectionFormat():SelectionFormat;
+
+		/**
+		 * Gets the character format attributes that are common to all characters in the specified text range or current selection.
+		 * 
+		 * <p>Format attributes that do not have the same value for all characters in the specified element range or selection are set to 
+		 * <code>null</code> in the returned ITextLayoutFormat instance.</p>
+		 * 
+		 * @param range The optional range of text for which common attributes are requested. If null, the current selection is used. 
+		 * @return The common character style settings
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonCharacterFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function getCommonCharacterFormat (range:TextRange=null):ITextLayoutFormat;
+		 
+		 /**
+		 * Gets the paragraph format attributes that are common to all paragraphs in the specified text range or current selection.
+		 * 
+		 * <p>Format attributes that do not have the same value for all paragraphs in the specified element range or selection are set to 
+		 * <code>null</code> in the returned ITextLayoutFormat instance.</p>
+		 * 
+		 * @param range The optional range of text for which common attributes are requested. If null, the current selection is used. 
+		 * @return The common paragraph style settings
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonParagraphFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function getCommonParagraphFormat (range:TextRange=null):ITextLayoutFormat;
+		 
+		/**
+		 * Gets the container format attributes that are common to all containers in the specified text range or current selection.
+		 * 
+		 * <p>Format attributes that do not have the same value for all containers in the specified element range or selection are set to 
+		 * <code>null</code> in the returned ITextLayoutFormat instance.</p>
+		 * 
+		 * @param range The optional range of text for which common attributes are requested. If null, the current selection is used. 
+		 * @return The common container style settings
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonContainerFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function getCommonContainerFormat (range:TextRange=null):ITextLayoutFormat;
+
+		/**
+		 * The editing mode. 
+		 * 
+		 * <p>The editing mode indicates whether the text flow supports selection, editing, or only reading.
+		 * A text flow is made selectable by assigning a selection manager and editable by assigning an edit manager.
+		 * Constants representing the editing modes are defined in the EditingMode class.</p>
+		 * 
+		 * @see flashx.textLayout.EditingMode
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		 function get editingMode():String;		
+		
+		/**
+		 * The SelectionFormat object used to draw the selection in a focused container. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */		 
+		 function get focusedSelectionFormat():SelectionFormat;
+		 function set focusedSelectionFormat(val:SelectionFormat):void;
+		 
+		/**
+		 * The SelectionFormat object used to draw the selection when it is not in a focused container, but is in
+		 * the active window.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */		 		 
+		 function get unfocusedSelectionFormat():SelectionFormat;
+		 function set unfocusedSelectionFormat(val:SelectionFormat):void;
+		 
+		/**
+		 * The SelectionFormat object used to draw the selection when it is not in the active window.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */		 		 
+		 function get inactiveSelectionFormat():SelectionFormat;
+		 function set inactiveSelectionFormat(val:SelectionFormat):void;		 		 
+		
+		/**
+		 * Executes any pending FlowOperations. 
+		 * 
+		 * <p>The execution of some editing operations, such as text insertion, is delayed 
+		 * until the next enterFrame event. Calling <code>flushPendingOperations()</code> causes any deferred operations to be executed 
+		 * immediately.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 * 
+		 */
+		function flushPendingOperations():void;
+
+		/** 
+		 * Updates the selection manager when text is inserted or deleted.
+		 * 
+		 * <p>Operations must call <code>notifyInsertOrDelete</code> when changing the text in the text flow. 
+		 * The selection manager adjusts index-based position indicators accordingly. If you create a new Operation
+		 * class that changes text in a text flow directly (not using another operation) your operation must call this function 
+		 * to keep the selection up to date.</p>
+		 * 
+		 * @param absolutePosition	The point in the text where the change was made.
+		 * @param length A positive or negative number indicating how many characters were inserted or deleted.
+		 * 
+		 * @includeExample examples\SelectionManager_notifyInsertOrDelete.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function notifyInsertOrDelete(absolutePosition:int, length:int):void		 
+		 	
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/edit/SelectionFormat.as b/textLayout_core/src/flashx/textLayout/edit/SelectionFormat.as
new file mode 100755
index 0000000..efe5bd7
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/edit/SelectionFormat.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 flashx.textLayout.edit
+{
+	import flash.display.BlendMode;
+	
+	/**
+	 * The SelectionFormat class defines the properties of a selection highlight.
+	 * 
+	 * @see flashx.textLayout.edit.ISelectionManager
+	 * @see flashx.textLayout.edit.SelectionManager
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public class SelectionFormat
+	{
+		private var _rangeColor:uint;
+		private var _rangeAlpha:Number;
+		private var _rangeBlendMode:String;
+		
+		private var _pointColor:uint;
+		private var _pointAlpha:Number;
+		private var _pointBlendMode:String;
+		private var _pointBlinkRate:Number;
+		
+		/** 
+		 * Creates a SelectionFormat object with the specified properties.
+		 * 
+		 * <p>A SelectionFormat created with the default values will use black for
+		 * the highlight colors, 1.0 for the alphas, and BlendMode.DIFFERENCE for the blending modes.
+		 * The cursor blink rate is 500 milliseconds.</p>
+		 *
+		 * <p>Setting the <code>pointAlpha</code> and <code>rangeAlpha</code> properties to zero disables selection highlighting.</p>
+		 * 
+		 * @param rangeColor The color for drawing the highlight.
+		 * @param rangeAlpha The transparency value for drawing the highlight. Valid values are between 0
+		 * (completely transparent) and 1 (completely opaque, which is the default).
+		 * @param rangeBlendMode The blend mode for drawing the highlight. Use constants defined in the BlendMode class
+		 * to set this parameter.
+		 * @param pointColor The color for the drawing cursor.
+		 * @param pointAlpha The transparency value for drawing the cursor. Valid values are between 0
+		 * (completely transparent) and 1 (completely opaque, which is the default).
+		 * @param pointBlendMode The blend mode for drawing the cursor. Use constants defined in the BlendMode class
+		 * to set this parameter.
+		 * @param pointBlinkRate The rate at which the cursor blinks, in milliseconds.
+		 * 
+		 * @see flash.display.BlendMode
+		 * @see #pointAlpha
+		 * @see #rangeAlpha
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function SelectionFormat(rangeColor:uint=0xffffff, rangeAlpha:Number=1.0, rangeBlendMode:String="difference", pointColor:uint=0xffffff, pointAlpha:Number=1.0, pointBlendMode:String="difference", pointBlinkRate:Number = 500)
+		{ 
+			_rangeColor = rangeColor;
+			_rangeAlpha = rangeAlpha;
+			_rangeBlendMode = rangeBlendMode;
+			
+			_pointColor = pointColor;
+			_pointAlpha = pointAlpha;
+			_pointBlendMode = pointBlendMode;
+			_pointBlinkRate = pointBlinkRate;
+		}
+		
+		/**
+		 * The color for drawing the highlight of a range selection. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function get rangeColor():uint
+		{
+			return _rangeColor;
+		}
+
+		/**
+		 * The alpha for drawing the highlight of a range selection. Valid values are between 0
+		 * (completely transparent) and 1 (completely opaque, which is the default).
+		 *
+		 * <p>Setting the <code>pointAlpha</code> and <code>rangeAlpha</code> properties to zero disables selection highlighting.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 *
+ 	 	 * @see #pointAlpha
+		 */						
+		public function get rangeAlpha():Number
+		{
+			return _rangeAlpha;
+		}
+
+		/**
+		 * The blending mode for drawing the highlight of a range selection. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @see flash.display.BlendMode
+		 */						
+		public function get rangeBlendMode():String
+		{
+			return _rangeBlendMode;
+		}
+		
+		/**
+		 * The color for drawing the cursor.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function get pointColor():uint
+		{
+			return _pointColor;
+		}
+
+		/**
+		 * The alpha for drawing the cursor. Valid values are between 0
+		 * (completely transparent) and 1 (completely opaque, which is the default).
+		 *
+		 * <p>Setting the <code>pointAlpha</code> and <code>rangeAlpha</code> properties to zero disables selection highlighting.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 *
+ 	 	 * @see #rangeAlpha
+		 */						
+		public function get pointAlpha():Number
+		{
+			return _pointAlpha;
+		}
+		
+		/**
+		 * The rate at which the cursor blinks, in milliseconds.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */						
+		public function get pointBlinkRate():Number
+		{
+			return _pointBlinkRate;
+		}		
+
+		/**
+		 * The blend mode for drawing the cursor.
+		 * 
+		 * @see flash.display.BlendMode
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */						
+		public function get pointBlendMode():String
+		{
+			return _pointBlendMode;
+		}
+
+		/**
+		 * Determines whether this SelectionFormat object has the same property values
+		 * as another SelectionFormat object.
+		 *  
+		 * @return <code>true</code>, if the property values are identical; <code>false</code>, otherwise.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * 
+		 * @param selectionFormat	the SelectionFormat to compare against.
+		 */								
+		public function equals(selectionFormat:SelectionFormat):Boolean
+		{
+			if ((_rangeBlendMode == selectionFormat.rangeBlendMode) &&
+				(_rangeAlpha == selectionFormat.rangeAlpha) &&
+				(_rangeColor == selectionFormat.rangeColor) &&
+				(_pointColor == selectionFormat.pointColor) &&
+				(_pointAlpha == selectionFormat.pointAlpha) &&
+				(_pointBlendMode == selectionFormat.pointBlendMode) &&
+				(_pointBlinkRate == selectionFormat.pointBlinkRate))
+				return true;
+			return false;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/edit/SelectionState.as b/textLayout_core/src/flashx/textLayout/edit/SelectionState.as
new file mode 100755
index 0000000..0044250
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/edit/SelectionState.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.edit
+{
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+	/**
+	 * The SelectionState class represents a selection in a text flow.  
+	 * 
+	 * <p>A selection range has an anchor point, representing the point at which the selection of text began, and an
+	 * active point, representing the point to which the selection is extended. The active point can be before or after 
+	 * the anchor point in the text. If a selection is modified (for example, by a user shift-clicking with the mouse),
+	 * the active point changes while the anchor point always remains in the same position.</p>
+	 *
+	 * @see flashx.textLayout.edit.ISelectionManager#getSelectionState()
+	 * @see flashx.textLayout.elements.TextFlow
+	 * @see flashx.textLayout.elements.TextRange
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+ 	 */
+	public class SelectionState extends TextRange
+	{		
+		/** Format that are associated with the caret position & will be applied to inserted text */
+		private var _pointFormat:ITextLayoutFormat;
+		
+		private var _selectionManagerOperationState:Boolean;
+
+		/** 
+		 * Creates a SelectionState object.
+		 * 
+		 * <p><b>Note:</b> Do not construct a SelectionState object in order to create a selection. To
+		 * create a selection in a text flow, call the <code>setSelection()</code> method of the relevant
+		 * ISelectionManager instance (which is the SelectionManager or EditManager object assigned 
+		 * to the <code>interactionManager</code> property of the text flow).</p>
+		 * 
+		 * @param	root	The TextFlow associated with the selection.
+		 * @param anchorPosition	The anchor index of the selection.
+		 * @param activePosition	The active index of the selection.
+		 * @param	format	The TextLayoutFormat to be applied on next character typed when a point selection
+		 * 
+		 * @see flashx.textLayout.edit.ISelectionManager#getSelectionState()
+		 * @see flashx.textLayout.edit.SelectionManager
+		 * @see flashx.textLayout.edit.EditManager
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function SelectionState(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null)
+		{
+			super(root, anchorPosition, activePosition);
+			if (format && !TextLayoutFormat.isEqual(format, TextLayoutFormat.emptyTextLayoutFormat))
+				_pointFormat = format;
+		}
+		
+		/** 
+		 * Updates the selection range with new anchor or active position values.  
+		 * 
+		 * <p>The <code>pointFormat</code> styles are cleared if the selection is changed.</p>
+		 * 
+		 * @param newAnchorPosition	the anchor index of the selection.
+		 * @param newActivePosition	the active index of the selection.
+		 * @return true if selection is changed
+		 * 
+		 */
+		public override function updateRange(newAnchorPosition:int,newActivePosition:int):Boolean
+		{
+			if (super.updateRange(newAnchorPosition,newActivePosition) )
+			{
+				_pointFormat = null;
+				return true;
+			}
+			return false;
+		}
+		
+		/** 
+		 * The format attributes applied to inserted text. 
+		 * 
+		 * <p><b>Note:</b> The <code>pointFormat</code> object does not include inherited styles. To
+		 * get all the applicable style definitions, use the <code>getCommonCharacterFormat()</code>
+		 * method of the ISelectionManager class.</p>
+		 * 
+		 * @see ISelectionManager#getCommonCharacterFormat()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */												
+		public function get pointFormat():ITextLayoutFormat
+		{ return _pointFormat; }
+		public function set pointFormat(format:ITextLayoutFormat):void
+		{ _pointFormat = format; } 
+		
+		/** @private used to tell an operation that the SelectionState is from the SelectionManager and that the SelectionManager pointFormat should be updated. */
+		tlf_internal function get selectionManagerOperationState():Boolean
+		{ return _selectionManagerOperationState; }
+		/** @private */		
+		tlf_internal function set selectionManagerOperationState(val:Boolean):void
+		{ _selectionManagerOperationState = val; }
+		/** @private */
+		tlf_internal function clone():SelectionState
+		{ return new SelectionState(textFlow,anchorPosition,activePosition,pointFormat); }
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/BackgroundManager.as b/textLayout_core/src/flashx/textLayout/elements/BackgroundManager.as
new file mode 100755
index 0000000..6695725
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/BackgroundManager.as
@@ -0,0 +1,176 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.display.Shape;
+	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.events.DamageEvent;
+	import flashx.textLayout.formats.BackgroundColor;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.GeometryUtil;
+	
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** @private Manages bounds calculation and rendering of backgroundColor character format. */
+	public class BackgroundManager
+	{
+		private var _textFlow:TextFlow;
+		private var _lineDict:Dictionary;
+
+		public function BackgroundManager():void
+		{
+			_lineDict = new Dictionary(true);
+		}	
+			
+		public function set textFlow(t:TextFlow):void
+		{
+			_textFlow = t;
+		}
+		
+		public function get textFlow():TextFlow
+		{
+			return _textFlow;
+		}
+		
+		public function addRect(line:TextFlowLine, fle:FlowLeafElement, r:Rectangle, color:uint, alpha:Number):void
+		{
+			var tl:TextLine = line.getTextLine();
+			
+			if(_lineDict[tl] == null)
+			{
+				_lineDict[tl] = new Array();
+			}
+			var obj:Object = new Object();
+			obj.rect = r;
+			obj.fle = fle;
+			obj.color = color;
+			obj.alpha = alpha;
+			var insert:Boolean = true;
+			var fleAbsoluteStart:int = fle.getAbsoluteStart();
+			
+			for(var i:int = 0; i < _lineDict[tl].length; ++i)
+			{
+				if(_lineDict[tl][i].fle.getAbsoluteStart() == fleAbsoluteStart)
+				{
+					_lineDict[tl][i] = obj;
+					insert = false;
+				}
+			}
+			if(insert)
+			{
+				_lineDict[tl].push(obj);
+			}
+		}
+		
+		public function finalizeLine(line:TextFlowLine):void
+		{ return; }	// nothing to do here
+		
+		/** @private */
+		tlf_internal function get lineDict():Dictionary
+		{
+			return _lineDict;
+		}
+		
+		// This version is used for the TextLineFactory
+		public function drawAllRects(bgShape:Shape,controller:ContainerController):void
+		{
+			for (var line:Object in _lineDict)
+			{
+				var a:Array = _lineDict[line];
+				if(a.length)
+				{
+					var columnRect:Rectangle = a[0].columnRect;	// set in TextLineFactoryBase.finalizeLine
+					var r:Rectangle;
+					var obj:Object;
+					for(var i:int = 0; i<a.length; ++i)
+					{
+						obj = a[i];
+						r = obj.rect;
+						r.x += line.x;
+						r.y += line.y;
+						TextFlowLine.constrainRectToColumn(textFlow, r, columnRect, 0, 0, controller.compositionWidth, controller.compositionHeight)						
+						
+						bgShape.graphics.beginFill(obj.color, obj.alpha);
+						bgShape.graphics.moveTo(r.left, r.top);
+						bgShape.graphics.lineTo(r.right, r.top);
+						bgShape.graphics.lineTo(r.right, r.bottom);
+						bgShape.graphics.lineTo(r.left, r.bottom);
+						bgShape.graphics.endFill();
+					}
+				}
+			}
+		}		
+		
+		public function removeLineFromCache(tl:TextLine):void
+		{
+			delete _lineDict[tl];
+		}
+
+		// This version is used for the TextFlow/flowComposer standard model
+		public function onUpdateComplete(controller:ContainerController):void
+		{
+			var container:DisplayObjectContainer = controller.container as DisplayObjectContainer;
+			var bgShape:Shape;
+			
+			if(container && container.numChildren)
+			{
+				bgShape = controller.getBackgroundShape();
+				bgShape.graphics.clear();
+				
+				for(var childIdx:int = 0; childIdx<controller.textLines.length; ++childIdx)
+				{
+					var tl:TextLine = controller.textLines[childIdx];
+		
+					if(_lineDict[tl])
+					{
+						if(!_lineDict[tl].length) 
+						{
+							continue;
+						}	
+						
+						for(var i:int = 0; i<_lineDict[tl].length; ++i)
+						{
+							var r:Rectangle = _lineDict[tl][i].rect.clone();
+							var tfl:TextFlowLine = tl.userData as TextFlowLine;
+							//make sure we actually got a tlf from the userData
+							if(tfl)
+								tfl.convertLineRectToContainer(r, true);
+							
+							bgShape.graphics.beginFill(_lineDict[tl][i].color, _lineDict[tl][i].alpha);
+							bgShape.graphics.moveTo(r.left, r.top);
+							bgShape.graphics.lineTo(r.right, r.top);
+							bgShape.graphics.lineTo(r.right, r.bottom);
+							bgShape.graphics.lineTo(r.left, r.bottom);
+							bgShape.graphics.endFill();
+						}
+					}
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/BreakElement.as b/textLayout_core/src/flashx/textLayout/elements/BreakElement.as
new file mode 100755
index 0000000..86929b3
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/BreakElement.as
@@ -0,0 +1,65 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.text.engine.TextElement;
+	
+	import flashx.textLayout.debug.assert;
+	
+	/** 
+	* The BreakElement class defines a line break, which provides for creating a line break in the text without 
+	* creating a new paragraph. It inserts a U+2028 character in the text of the paragraph.
+	*
+	* <p><strong>Note</strong>: This class exists primarily to support break <br/> tags in MXML markup. To create line breaks, 
+	* you can add newline characters (\n) directly into the text like this:</p>
+	*
+	* <listing version="3.0" >
+	* spanElement1.text += '\n';
+	* </listing>
+	*
+	* In markup, either FXG, TEXT_LAYOUT_FORMAT or MXML, you can simply insert a <br/> where you want the break.
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*
+	* @see ParagraphElement
+	* @see SpanElement
+	*/
+	public final class BreakElement extends SpecialCharacterElement
+	{
+		/** Constructor. 
+		*
+		* @playerversion Flash 10 
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		public function BreakElement()
+		{
+			super();
+			this.text = '\u2028';
+		}
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/Configuration.as b/textLayout_core/src/flashx/textLayout/elements/Configuration.as
new file mode 100755
index 0000000..d2958b4
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/Configuration.as
@@ -0,0 +1,536 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.BlendMode;
+	import flash.system.Capabilities;
+	import flash.text.engine.TextBlock;
+	
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.edit.SelectionFormat;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextDecoration;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	* The Configuration class is a primary point of integration between the Text Layout Framework and an application. You can 
+	* include a Configuration object as a parameter to the <code>TextFlow()</code> constructor when you create a new TextFlow
+	* instance. It allows the application to initially control how the Text Layout Framework behaves.
+	* 
+	* <p>The Configuration class allows you to specify initial, paragraph and container formats for the text flow 
+	* through the <code>textFlowInitialFormat</code> property. It also allows you to specify initial format attributes for links, selection,
+	* scrolling, and for handling the Tab and Enter keys.</p>
+	*
+	* @includeExample examples\ConfigurationExample.as -noswf
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	* 
+	* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+	* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+	* @see TextFlow
+	*/
+	
+	public class Configuration implements IConfiguration
+	{
+		/** @private */
+		static tlf_internal function versionIsAtLeast(major:int,minor:int):Boolean
+		{ 
+			var versionData:Array = Capabilities.version.split(" ")[1].split(","); 
+			return int(versionData[0]) > major || (int(versionData[0]) == major && int(versionData[1]) >= minor);
+		}
+		
+		/** @private The player may disable the feature for older swfs.  */
+		static tlf_internal const playerEnablesArgoFeatures:Boolean = versionIsAtLeast(10,1) && (new TextBlock).hasOwnProperty("recreateTextLine"); 
+		
+		/** If manageTabKey and manageEnterKey are false, the client must handle those keys on their own. */
+		private var _manageTabKey:Boolean;
+		private var _manageEnterKey:Boolean;
+		
+		private var _overflowPolicy:String;
+		
+		private var _enableAccessibility:Boolean;
+		private var _releaseLineCreationData:Boolean;
+		
+		// TODO: make me into dictionaries
+		private var _defaultLinkNormalFormat:ITextLayoutFormat;
+		private var _defaultLinkActiveFormat:ITextLayoutFormat;
+		private var _defaultLinkHoverFormat:ITextLayoutFormat;
+		
+		private var _textFlowInitialFormat:ITextLayoutFormat;
+		
+		private var _focusedSelectionFormat:SelectionFormat;
+		private var _unfocusedSelectionFormat:SelectionFormat;
+		private var _inactiveSelectionFormat:SelectionFormat;	
+		
+		// scrolling vars
+		private var _scrollDragDelay:Number;
+		private var _scrollDragPixels:Number;
+		private var _scrollPagePercentage:Number;
+		private var _scrollMouseWheelMultiplier:Number;
+		
+		private var _flowComposerClass:Class;
+		private var _inlineGraphicResolverFunction:Function;
+				
+		/** Constructor - creates a default configuration. 
+		*
+		* @param initializeWithDefaults Specifies whether to initialize the configuration with
+		* the default values. Default is <code>true</code>. If set to <code>false</code>, initializes
+		* without default values, thereby saving some objects. The <code>clone()</code> method sets this
+		* to <code>false</code> and copies the properties from the original object.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	* 
+		* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.compose.StandardFlowComposer StandardFlowComposer
+		*/
+		public function Configuration(initializeWithDefaults:Boolean = true)
+		{
+			if (initializeWithDefaults)
+				initialize()
+		}
+		
+		private function initialize():void
+		{
+			var scratchFormat:TextLayoutFormatValueHolder;
+	
+			_manageTabKey = false;
+			_manageEnterKey = true;
+			_overflowPolicy = OverflowPolicy.FIT_DESCENDERS;
+			_enableAccessibility = false;
+			_releaseLineCreationData = false;
+			
+			_focusedSelectionFormat = new SelectionFormat(0xffffff, 1.0, BlendMode.DIFFERENCE);
+			_unfocusedSelectionFormat = new SelectionFormat(0xffffff, 0, BlendMode.DIFFERENCE, 0xffffff, 0.0, BlendMode.DIFFERENCE, 0);
+			_inactiveSelectionFormat  = _unfocusedSelectionFormat;
+				
+			scratchFormat = new TextLayoutFormatValueHolder();
+			scratchFormat.textDecoration = TextDecoration.UNDERLINE;
+			scratchFormat.color = 0x0000FF;//default link color is blue
+			_defaultLinkNormalFormat = scratchFormat;
+				
+			scratchFormat = new TextLayoutFormatValueHolder();
+			scratchFormat.lineBreak = FormatValue.INHERIT;
+			scratchFormat.paddingLeft = FormatValue.INHERIT;
+			scratchFormat.paddingRight = FormatValue.INHERIT;
+			scratchFormat.paddingTop = FormatValue.INHERIT;
+			scratchFormat.paddingBottom = FormatValue.INHERIT;
+			scratchFormat.verticalAlign = FormatValue.INHERIT;
+			scratchFormat.columnCount = FormatValue.INHERIT;
+			scratchFormat.columnCount = FormatValue.INHERIT;
+			scratchFormat.columnGap = FormatValue.INHERIT;
+			scratchFormat.columnWidth = FormatValue.INHERIT;
+			_textFlowInitialFormat = scratchFormat;
+					
+			_scrollDragDelay = 35;
+			_scrollDragPixels = 20;
+			_scrollPagePercentage = 7.0/8.0;
+			_scrollMouseWheelMultiplier = 20;
+				
+			_flowComposerClass = StandardFlowComposer;
+		}
+		
+		private var _immutableClone:IConfiguration;
+		
+		/** TextFlows are configured with an immutable clone of a Configuration.  Once a TextFlow is create it uses an immutable configuration. @private */
+		tlf_internal function getImmutableClone():IConfiguration
+		{
+			if (!_immutableClone)
+			{
+				var clonedConifg:Configuration = clone();
+				_immutableClone = clonedConifg;
+				// an immutable clone is its own immutable clone
+				clonedConifg._immutableClone = clonedConifg;
+			}
+			return _immutableClone; 
+		}
+		
+		/** Creates a clone of the Configuration object.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+		public function clone():Configuration
+		{
+			var config:Configuration = new Configuration(false);
+			// must copy all values
+			config.defaultLinkActiveFormat = defaultLinkActiveFormat;
+			config.defaultLinkHoverFormat  = defaultLinkHoverFormat;
+			config.defaultLinkNormalFormat = defaultLinkNormalFormat;
+			config.textFlowInitialFormat = _textFlowInitialFormat;
+			config.focusedSelectionFormat = _focusedSelectionFormat;
+			config.unfocusedSelectionFormat = _unfocusedSelectionFormat;
+			config.inactiveSelectionFormat = _inactiveSelectionFormat;
+			
+			config.manageTabKey = _manageTabKey;
+			config.manageEnterKey = _manageEnterKey;
+			config.overflowPolicy = _overflowPolicy;
+			config.enableAccessibility = _enableAccessibility;
+			config.releaseLineCreationData = _releaseLineCreationData;
+			
+			config.scrollDragDelay = _scrollDragDelay;
+			config.scrollDragPixels = _scrollDragPixels;
+			config.scrollPagePercentage = _scrollPagePercentage;
+			config.scrollMouseWheelMultiplier = _scrollMouseWheelMultiplier;
+			
+			config.flowComposerClass = _flowComposerClass;
+			config._inlineGraphicResolverFunction = _inlineGraphicResolverFunction;
+			return config; 
+		}
+		
+		/** @copy IConfiguration#manageTabKey
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get manageTabKey():Boolean
+		{ return _manageTabKey; }
+		public function set manageTabKey(val:Boolean):void
+		{ _manageTabKey = val; _immutableClone = null; }
+
+		/** 
+		* @copy IConfiguration#manageEnterKey
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get manageEnterKey():Boolean
+		{ return _manageEnterKey; }
+		public function set manageEnterKey(val:Boolean):void
+		{ _manageEnterKey = val; _immutableClone = null; }
+		
+
+		
+		/** 
+		* @copy IConfiguration#overflowPolicy
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see OverflowPolicy
+		*/
+
+		public function get overflowPolicy():String
+		{ 	return _overflowPolicy; }
+		public function set overflowPolicy(value:String):void
+		{ 	_overflowPolicy = value; }
+				
+		/** 
+		* @copy IConfiguration#defaultLinkNormalFormat
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see FlowElement#linkNormalFormat
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		public function get defaultLinkNormalFormat():ITextLayoutFormat
+		{ return _defaultLinkNormalFormat; }
+		public function set defaultLinkNormalFormat(val:ITextLayoutFormat):void
+		{ _defaultLinkNormalFormat = val; _immutableClone = null; }
+		
+		/** 
+		* @copy IConfiguration#defaultLinkHoverFormat  
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see  FlowElement#linkHoverFormat
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		public function get defaultLinkHoverFormat():ITextLayoutFormat
+		{ return _defaultLinkHoverFormat; }	
+		public function set defaultLinkHoverFormat(val:ITextLayoutFormat):void
+		{ _defaultLinkHoverFormat = val; _immutableClone = null; }
+			
+		/** 
+		* @copy IConfiguration#defaultLinkActiveFormat
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see FlowElement#linkActiveFormat 
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		public function get defaultLinkActiveFormat():ITextLayoutFormat
+		{ return _defaultLinkActiveFormat; }
+		public function set defaultLinkActiveFormat(val:ITextLayoutFormat):void
+		{ _defaultLinkActiveFormat = val; _immutableClone = null; }
+		
+		/** 
+		* @copy IConfiguration#textFlowInitialFormat
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see TextFlow
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		*/
+		
+		public function get textFlowInitialFormat():ITextLayoutFormat
+		{ return _textFlowInitialFormat; }
+		public function set textFlowInitialFormat(val:ITextLayoutFormat):void
+		{ _textFlowInitialFormat = val; _immutableClone = null; }
+		
+
+		
+		/** 
+		* @copy IConfiguration#focusedSelectionFormat 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#focusedSelectionFormat SelectionManager.focusedSelectionFormat
+		* @see TextFlow
+		*/
+		
+		public function get focusedSelectionFormat():SelectionFormat
+		{ return _focusedSelectionFormat; }
+		public function set focusedSelectionFormat(val:SelectionFormat):void
+		{	if (val != null)
+			{	
+				_focusedSelectionFormat = val; 
+				_immutableClone = null;
+			} 
+		}
+		
+		/** 
+		* @copy IConfiguration#unfocusedSelectionFormat
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#unfocusedSelectionFormat SelectionManager.unfocusedSelectionFormat
+		* @see TextFlow
+		*/
+		
+		public function get unfocusedSelectionFormat():SelectionFormat
+		{ return _unfocusedSelectionFormat; }
+		public function set unfocusedSelectionFormat(val:SelectionFormat):void
+		{	if (val != null)
+			{	
+				_unfocusedSelectionFormat = val; 
+				_immutableClone = null;
+			} 
+		}		
+		
+		/** 
+		* @copy IConfiguration#inactiveSelectionFormat
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#inactiveSelectionFormat SelectionManager.inactiveSelectionFormat
+		* @see TextFlow
+		*/
+		
+		public function get inactiveSelectionFormat():SelectionFormat
+		{ return _inactiveSelectionFormat; }
+		public function set inactiveSelectionFormat(val:SelectionFormat):void
+		{	
+			if (val != null)
+			{
+				_inactiveSelectionFormat = val; 
+				_immutableClone = null; 
+			}
+		}												
+		
+		/** 
+		* @copy IConfiguration#scrollDragDelay
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get scrollDragDelay():Number
+		{ return _scrollDragDelay; }
+		public function set scrollDragDelay(val:Number):void
+		{
+			if (val > 0) {
+				_scrollDragDelay = val;
+				_immutableClone = null;
+			}
+		}
+		
+		/** 
+		* @copy IConfiguration#scrollDragPixels
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get scrollDragPixels():Number
+		{ return _scrollDragPixels; }
+		public function set scrollDragPixels(val:Number):void
+		{
+			if (val > 0) {
+				_scrollDragPixels = val;
+				_immutableClone = null;
+			}
+		}
+
+		/**
+		* @copy IConfiguration#scrollPagePercentage
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get scrollPagePercentage(): Number
+		{ return _scrollPagePercentage; }
+		public function set scrollPagePercentage(val:Number):void
+		{
+			if (val > 0) {
+				_scrollPagePercentage = val;
+				_immutableClone = null;
+			}
+		}
+		
+		/** 
+		* @copy IConfiguration#scrollMouseWheelMultiplier
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*/
+		
+		public function get scrollMouseWheelMultiplier(): Number
+		{ return _scrollMouseWheelMultiplier; }
+		public function set scrollMouseWheelMultiplier(val:Number):void
+		{
+			if (val > 0) {
+				_scrollMouseWheelMultiplier = val;
+				_immutableClone = null;
+			}
+		}
+		
+		/** 
+		* @copy IConfiguration#flowComposerClass
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see flashx.textLayout.compose.StandardFlowComposer StandardFlowComposer
+		* @see flashx.textLayout.elements.TextFlow TextFlow
+		*/
+		
+		public function get flowComposerClass(): Class
+		{ return _flowComposerClass; }
+		public function set flowComposerClass(val:Class):void
+		{
+			_flowComposerClass = val;
+			_immutableClone = null;
+		}
+	
+		/** 
+		* @copy IConfiguration#enableAccessibility
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see TextFlow
+		*/
+		
+		public function get enableAccessibility():Boolean
+		{ return _enableAccessibility; }
+		public function set enableAccessibility(val:Boolean):void
+		{
+			_enableAccessibility = val;
+			_immutableClone = null;
+		}
+		
+		/** 
+		* @copy IConfiguration#releaseLineCreationData
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.compose.StandardFlowComposer StandardFlowComposer
+		* @see flash.text.engine.TextBlock#releaseLineCreationData() TextBlock.releaseLineCreationData()
+		*/
+		
+		public function get releaseLineCreationData():Boolean
+		{ return _releaseLineCreationData; }
+		public function set releaseLineCreationData(val:Boolean):void
+		{
+			_releaseLineCreationData = val;
+			_immutableClone = null;
+		}
+					
+		/** Returns true if the ActionScript text engine was built with debugging code enabled. @private */
+		static tlf_internal function get debugCodeEnabled():Boolean
+		{
+			CONFIG::debug   { return true; }
+			CONFIG::release { return false; }
+		}
+		
+		/** 
+		* @copy IConfiguration#inlineGraphicResolverFunction
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.elements.InlineGraphicElement InlineGraphicElement
+		*/		
+		public function get inlineGraphicResolverFunction():Function
+		{ 
+			return _inlineGraphicResolverFunction; 
+		}
+		public function set inlineGraphicResolverFunction(val:Function):void
+		{
+			_inlineGraphicResolverFunction = val;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/ContainerFormattedElement.as b/textLayout_core/src/flashx/textLayout/elements/ContainerFormattedElement.as
new file mode 100755
index 0000000..452a149
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/ContainerFormattedElement.as
@@ -0,0 +1,127 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.DisplayObjectContainer;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FlowElementDisplayType;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	/** 
+	* ContainerFormattedElement is the root class for all container-level block elements, such as DivElement
+	* and TextFlow objects. Container-level block elements are grouping elements for other FlowElement objects.
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*
+	* @see DivElement
+	* @see TextFlow
+	*/	
+	public class ContainerFormattedElement extends ParagraphFormattedElement
+	{
+		private var _display:String;	// FlowElementDisplayType
+
+		/** @private */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			if (endPos == -1)
+				endPos = textLength;
+				
+			var retFlow:ContainerFormattedElement = super.shallowCopy(startPos, endPos) as ContainerFormattedElement;
+			retFlow._display = _display;	
+			return retFlow;						
+		}
+
+		/** @private */
+		public override function get display():String
+		{
+			return _display;
+		} 
+		/** @private */
+		public function set display(value:String):void
+		{
+			CONFIG::debug { assert(value == FlowElementDisplayType.INLINE || value == FlowElementDisplayType.FLOAT, "Illegal value for display"); }
+			_display = value;
+		}
+		
+		/** @private */
+		public function get flowComposer():IFlowComposer
+		{ 
+			// TODO: this is here for legacy purposes.  What we really want to do is determine if a given element has its own physical representation
+			// That used to be the containerController and may be again.  This is all intermediate for now.  Reinvestigate when Tables are enabled and Div's with containers are implemented.
+			return null; 
+		}
+		
+		/** @private */
+		tlf_internal override function formatChanged(notifyModelChanged:Boolean = true):void
+		{
+			super.formatChanged(notifyModelChanged);
+			// The associated container, if there is one, inherits its container
+			// attributes from here. So we need to tell it that these attributes
+			// have changed.
+			if (flowComposer)
+			{
+				for (var idx:int = 0; idx < flowComposer.numControllers; idx++)
+					flowComposer.getControllerAt(idx).formatChanged();
+			}
+		}
+		
+		/** @private */
+		tlf_internal function preCompose():void
+		{ return; }
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			if (flowComposer && flowComposer.numControllers)
+			{
+				var controller:ContainerController = flowComposer.getControllerAt(0);
+				extraData = getDebugIdentity(controller.container)+" b:"+controller.absoluteStart+" l:" +controller.textLength+extraData;
+				extraData = extraData+" w:"+controller.compositionWidth+" h:"+controller.compositionHeight;
+			}
+			return super.debugCheckFlowElement(depth,extraData);
+		}
+		
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			super.normalizeRange(normalizeStart,normalizeEnd);
+			
+			// is this an absolutely element?
+			if (this.numChildren == 0)
+			{
+				var p:ParagraphElement = new ParagraphElement();
+				p.replaceChildren(0,0,new SpanElement());
+				replaceChildren(0,0,p);	
+				CONFIG::debug { assert(textLength == 1,"bad textlength"); }
+				p.normalizeRange(0,p.textLength);	
+			}
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/DivElement.as b/textLayout_core/src/flashx/textLayout/elements/DivElement.as
new file mode 100755
index 0000000..1eb2cd0
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/DivElement.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.elements
+{
+	import flashx.textLayout.debug.assert;	
+	
+	/** 
+	 * The DivElement class defines an element for grouping paragraphs (ParagraphElement objects). If you want a group of paragraphs
+	 * to share the same formatting attributes, you can group them in a DivElement object and apply the attributes to it. The paragraphs
+	 * will inherit the attributes from the DivElement object.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @includeExample examples\DivElementExample.as -noswf
+	 *
+	 * @see ParagraphElement
+	 * @see TextFlow
+	 */
+	public final class DivElement extends ContainerFormattedElement
+	{
+		/** Constructor - creates a new DivElement object.
+		*		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+		public function DivElement()
+		{
+			super();
+		}
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/FlowElement.as b/textLayout_core/src/flashx/textLayout/elements/FlowElement.as
new file mode 100755
index 0000000..32cb1ed
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/FlowElement.as
@@ -0,0 +1,1401 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.DisplayObjectContainer;
+	import flash.utils.Dictionary;
+	import flash.utils.getDefinitionByName;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.formats.FlowElementDisplayType;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	[IMXMLObject]	
+
+/**
+ * The text in a flow is stored in tree form with the elements of the tree representing logical
+ * divisions within the text. The FlowElement class is the abstract base class of all the objects in this tree.
+ * FlowElement objects represent paragraphs, spans of text within paragraphs, and
+ * groups of paragraphs.
+ *
+ * <p>The root of a composable FlowElement tree is always a TextFlow object. Leaf elements of the tree are always 
+ * subclasses of the FlowLeafElement class. All leaves arranged in a composable TextFlow have a ParagraphElement ancestor.
+ * </p> 
+ *
+ * <p>You cannot create a FlowElement object directly. Invoking <code>new FlowElement()</code> throws an error 
+ * exception.</p>
+ *
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ * 
+ * @see FlowGroupElement
+ * @see FlowLeafElement
+ * @see InlineGraphicElement
+ * @see ParagraphElement
+ * @see SpanElement
+ * @see TextFlow
+ */
+	public class FlowElement implements ITextLayoutFormat
+	{
+		/** every FlowElement has at most one parent */
+		private var _parent:FlowGroupElement;
+		
+		/** format settings on this FlowElement */
+		private var _formatValueHolder:FlowValueHolder;
+		
+		/** @private computed formats applied to the element */
+		protected var _computedFormat:ITextLayoutFormat;
+		
+		/** start, _start of element, relative to parent.  */
+		private var _parentRelativeStart:int = 0;		
+		
+		/** _textLength (number of chars) in the element, including child content */
+		private var _textLength:int = 0;	
+	
+		/** Base class - invoking <code>new FlowElement()</code> throws an error exception.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+		public function FlowElement()
+		{
+			// not a valid FlowElement class
+			if (abstract)
+				throw new Error(GlobalSettings.resourceStringFunction("invalidFlowElementConstruct"));
+		}
+		
+		/** Called for MXML objects after the implementing object has been created and all component properties specified on the MXML tag have been initialized. 
+		 * @param document The MXML document that created the object.
+		 * @param id The identifier used by document to refer to this object.
+		 **/
+		public function initialized(document:Object, id:String):void
+		{
+			this.id = id;
+		}
+
+		/** Returns true if the class is an abstract base class,
+		 * false if its OK to construct. Attempting to instantiate an
+		 * abstract FlowElement class will cause an exception.
+		 * @return Boolean 	true if this is an abstract class
+		 * @private
+		 */
+		protected function get abstract():Boolean
+		{
+			return true;
+		}
+		
+		/** Allows you to read and write user styles on a FlowElement object.  Note that reading this property
+		* makes a copy of the user-styles dictionary. 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+		*
+		*/
+		public function get userStyles():Object
+		{
+			var styles:Object = _formatValueHolder == null ? null : _formatValueHolder.userStyles;
+			return styles ? Property.shallowCopy(styles) : null;
+		}
+		public function set userStyles(styles:Object):void
+		{
+			var newStyles:Object;
+			if (styles)
+			{
+				newStyles = new Object();
+				for (var val:Object in styles)
+					newStyles[val] = styles[val];
+			}
+			writableTextLayoutFormatValueHolder().userStyles = newStyles;
+			modelChanged(ModelChange.USER_STYLE_CHANGED,0,this.textLength,true);
+		}
+		
+		/** Returns the core styles on a FlowElement instance. Returns a copy of the core styles. 
+		 *  
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 *
+		 */
+		 
+		public function get coreStyles():Object
+		{
+			var styles:Object = _formatValueHolder == null ? null : _formatValueHolder.coreStyles;
+			return styles ? Property.shallowCopy(styles) : null;
+		}
+		
+		/** @private */
+		tlf_internal function setCoreStylesInternal(styles:Object):void
+		{
+			var newStyles:Object;
+			if (styles)
+			{
+				newStyles = new Object();
+				for (var val:Object in styles)
+				{
+					var value:* = styles[val];
+					if (value != undefined)
+						newStyles[val] = value;
+				}
+			}
+			writableTextLayoutFormatValueHolder().coreStyles = newStyles;
+			formatChanged();		
+		}
+		
+
+		public function set linkNormalFormat(value:*):void
+		{ setStyle(LinkElement.LINK_NORMAL_FORMAT_NAME,value); }
+		/** Defines the formatting attributes used for links in normal state. This value will cascade down the hierarchy and apply to any links that are descendants.
+		 * Equivalent to setStyle(linkNormalFormat,value).  Expects a dictionary of properties.  Converts an array of objects with key and value as members to a dictionary. */
+		public function get linkNormalFormat():*
+		{ return getStyle(LinkElement.LINK_NORMAL_FORMAT_NAME); }
+		
+
+		public function set linkActiveFormat(value:*):void
+		{ setStyle(LinkElement.LINK_ACTIVE_FORMAT_NAME,value); }
+		/** Defines the formatting attributes used for links in active state, when the mouse is down on a link. This value will cascade down the hierarchy and apply to any links that are descendants.
+		 * Equivalent to setStyle(linkActiveFormat,value).  Expects a dictionary of properties.  Converts an array of objects with key and value as members to a dictionary. */
+		public function get linkActiveFormat():*
+		{ return getStyle(LinkElement.LINK_ACTIVE_FORMAT_NAME); }
+		
+
+		public function set linkHoverFormat(value:*):void
+		{ setStyle(LinkElement.LINK_HOVER_FORMAT_NAME,value); }
+		/** Defines the formatting attributes used for links in hover state, when the mouse is within the bounds (rolling over) a link. This value will cascade down the hierarchy and apply to any links that are descendants.
+		 * Equivalent to setStyle(linkHoverFormat,value).  Expects a dictionary of properties.  Converts an array of objects with key and value as members to a dictionary. */
+		public function get linkHoverFormat():*
+		{ return getStyle(LinkElement.LINK_HOVER_FORMAT_NAME); }
+		
+		/** Compare the userStyles of this with otherElement's userStyles. 
+		 *
+		 * @param otherElement the FlowElement object with which to compare user styles
+		 *
+		 * @return 	true if the user styles are equal; false otherwise.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+	 	 * @includeExample examples\FlowElement_equalUserStylesExample.as -noswf
+	 	 * 
+	 	 * @see #getStyle()
+	 	 * @see #setStyle()
+	 	 * @see #userStyles
+		 */
+		public function equalUserStyles(otherElement:FlowElement):Boolean
+		{
+			var myStyles:Object = _formatValueHolder ? _formatValueHolder.userStyles : null;
+			var elemStyles:Object = otherElement._formatValueHolder ? otherElement._formatValueHolder.userStyles : null;
+			return Property.equalStyleObjects(myStyles,elemStyles);
+		}
+		
+		/** @private Compare the styles of two elements for merging.  Return true if they can be merged. */
+		tlf_internal function equalStylesForMerge(elem:FlowElement):Boolean
+		{
+			return this.id == elem.id && this.styleName == elem.styleName && TextLayoutFormat.isEqual(elem.format,format) && equalUserStyles(elem);
+		}
+		
+		/**
+		 * Makes a copy of this FlowElement object, copying the content between two specified character positions.
+		 * It returns the copy as a new FlowElement object. Unlike <code>deepCopy()</code>, <code>shallowCopy()</code> does
+		 * not copy any of the children of this FlowElement object. 
+		 * 
+		 * <p>With no arguments, <code>shallowCopy()</code> defaults to copying all of the content.</p>
+		 *
+		 * @param relativeStart	The relative text position of the first character to copy. First position is 0.
+		 * @param relativeEnd	The relative text position of the last character to copy. A value of -1 indicates copy to end.
+		 *
+		 * @return 	the object created by the copy operation.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_shallowCopyExample.as -noswf
+		 *
+	 	 * @see #deepCopy()
+	 	 */
+		 
+		public function shallowCopy(relativeStart:int = 0, relativeEnd:int = -1):FlowElement
+		{
+			if (relativeEnd == -1)
+				relativeEnd = textLength;
+				
+			var retFlow:FlowElement = new (getDefinitionByName(getQualifiedClassName(this)) as Class);
+			retFlow.styleName = styleName;
+			retFlow.id = id;	// ???? copy me ?????
+			if (_formatValueHolder !=  null)
+				retFlow._formatValueHolder = new FlowValueHolder(_formatValueHolder);
+			return retFlow;
+		}
+
+		/**
+		 * Makes a deep copy of this FlowElement object, including any children, copying the content between the two specified
+		 * character positions and returning the copy as a FlowElement object.
+		 * 
+		 * <p>With no arguments, <code>deepCopy()</code> defaults to copying the entire element.</p>
+		 * 
+		 * @param relativeStart	relative text position of the first character to copy. First position is 0.
+		 * @param relativeEnd	relative text position of the last character to copy. A value of -1 indicates copy to end.
+		 *
+		 * @return 	the object created by the deep copy operation.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_deepCopyExample.as -noswf
+	 	 * 
+	 	 * @see #shallowCopy()
+		 */
+		 
+		public function deepCopy(relativeStart:int = 0, relativeEnd:int = -1):FlowElement
+		{
+			if (relativeEnd == -1)
+				relativeEnd = textLength;
+				
+			return shallowCopy(relativeStart, relativeEnd);
+		}
+		
+		/** 
+		 * Gets the specified range of text from a flow element.
+		 * 
+		 * @param relativeStart The starting position of the range of text to be retrieved, relative to the start of the FlowElement
+		 * @param relativeEnd The ending position of the range of text to be retrieved, relative to the start of the FlowElement, -1 for up to the end of the element
+		 * @param paragraphSeparator character to put between paragraphs
+		 * 
+		 * @return The requested text.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+		{
+			return "";
+		}
+
+		/** 
+		 * Splits this FlowElement object at the position specified by the <code>relativePosition</code> parameter, which is
+		 * a relative position in the text for this element. This method splits only SpanElement and FlowGroupElement 
+		 * objects.
+		 *
+		 * @param relativePosition the position at which to split the content of the original object, with the first position being 0.
+		 * 
+		 * @return	the new object, which contains the content of the original object, starting at the specified position.
+		 *
+		 * @throws RangeError if <code>relativePosition</code> is greater than <code>textLength</code>, or less than 0.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function splitAtPosition(relativePosition:int):FlowElement
+		{
+			if ((relativePosition < 0) || (relativePosition > textLength))
+				throw RangeError(GlobalSettings.resourceStringFunction("invalidSplitAtPosition"));
+			return this;
+		}
+		
+		/** @private Set to indicate the element may be "bound" in Flex - only used on FlowLeafElement and SubParagraphBlock elements. */
+		tlf_internal function get bindableElement():Boolean
+		{ return getPrivateStyle("bindable") == true; }
+		
+		/** @private */
+		tlf_internal function set bindableElement(value:Boolean):void
+		{ setPrivateStyle("bindable", value); }
+
+		
+		/** Merge flow element into previous flow element if possible. @private
+		 * @Return true--> did the merge
+		 */
+		 
+		tlf_internal function mergeToPreviousIfPossible():Boolean
+		{
+			return false;
+		}
+		
+		/** @private 
+		 * Create and initialize the FTE data structure that corresponds to the FlowElement
+		 */
+		tlf_internal function createContentElement():void
+		{
+			// overridden in the base class -- we should not get here
+			CONFIG::debug { assert(false,"invalid call to createContentElement"); }
+		}
+		
+		/** @private 
+		 * Release the FTE data structure that corresponds to the FlowElement, so it can be gc'ed
+		 */
+		tlf_internal function releaseContentElement():void
+		{
+			// overridden in the base class -- we should not get here
+			CONFIG::debug { assert(false,"invalid call to createContentElement"); }
+		}
+
+		/** @private 
+		 * True if it is safe to release the corresponding FTE data structure.
+		 */
+		tlf_internal function canReleaseContentElement():Boolean
+		{
+			return true;
+		}
+		
+		/** Returns the parent of this FlowElement object. Every FlowElement has at most one parent.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function get parent():FlowGroupElement
+		{ return _parent; }
+		
+		/** @private parent setter. */
+		
+		tlf_internal function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
+		{ _parent = newParent; _parentRelativeStart = newStart; attributesChanged(false); }
+		
+				
+		/** @private Used when the textBlock.content is already correctly configured. */
+		tlf_internal function setParentAndRelativeStartOnly(newParent:FlowGroupElement,newStart:int):void
+		{ _parent = newParent;  _parentRelativeStart = newStart; }
+			
+		/**
+		 * Returns the total length of text owned by this FlowElement object and its children.  If an element has no text, the 
+		 * value of <code>textLength</code> is usually zero. 
+		 * 
+		 * <p>ParagraphElement objects have a final span with a paragraph terminator character for the last 
+		 * SpanElement object.The paragraph terminator is included in the value of the <code>textLength</code> of that 
+		 * SpanElement object and all its parents.  It is not included in <code>text</code> property of the SpanElement
+		 * object.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #textLength
+		 */
+		 
+		public function get textLength():int
+		{ return _textLength; }
+		
+		/** @private textLength setter.  */
+		tlf_internal function setTextLength(newLength:int):void
+		{ _textLength = newLength; }	
+		
+		/** Returns the relative start of this FlowElement object in the parent. If parent is null, this value is always zero.  
+		 * If parent is not null, the value is the sum of the text lengths of all previous siblings.
+		 *
+		 * @return offset
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see #textLength
+		 */
+		 
+		public function get parentRelativeStart():int
+		{ return _parentRelativeStart; }
+		
+		/** @private start setter. */
+		tlf_internal function setParentRelativeStart(newStart:int):void
+		{ _parentRelativeStart = newStart; }
+		
+		/** Returns the relative end of this FlowElement object in the parent. If the parent is null this is always equal to <code>textLength</code>.  If 
+		 * the parent is not null, the value is the sum of the text lengths of this and all previous siblings, which is effectively
+		 * the first character in the next FlowElement object.
+		 *
+		 * @return offset
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see FlowGroupElement
+	 	 * @see #textLength
+		 */
+		 
+		public function get parentRelativeEnd():int
+		{ return _parentRelativeStart + _textLength; }
+				
+		/**
+		 * Tag for the item, used for debugging.
+		 */
+		CONFIG::debug public function get name():String
+		{
+			return flash.utils.getQualifiedClassName(this);
+		}
+		
+		/** Returns the ContainerFormattedElement that specifies its containers for filling. This ContainerFormattedElement
+		 * object has its own columns and can control ColumnDirection and BlockProgression. 
+		 *
+		 * @return 	the ancestor, with its container, of this FlowElement object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @private
+		 */
+		 
+		tlf_internal function getAncestorWithContainer():ContainerFormattedElement
+		{
+			var elem:FlowElement = this;
+			while (elem)
+			{
+				var contElement:ContainerFormattedElement = elem as ContainerFormattedElement;
+				if (contElement)
+				{
+					if (!contElement._parent || contElement.flowComposer)
+						return contElement;
+				}
+				elem = elem._parent; 
+			}
+			return null;
+		}
+		
+		
+		/**
+		 * @private
+		 * Generic mechanism for fetching private data from the element.
+		 * @param styleName	name of the property
+		 */
+		tlf_internal function getPrivateStyle(styleName:String):*
+		{ return _formatValueHolder ? _formatValueHolder.getPrivateData(styleName) : undefined; }
+
+		/**
+		 * @private
+		 * Generic mechanism for adding private data to the element.
+		 * @param styleName	name of the property
+		 * @param val value of the property
+		 */
+		tlf_internal function setPrivateStyle(styleName:String, val:*):void
+		{
+			if (getPrivateStyle(styleName) != val)
+			{
+				writableTextLayoutFormatValueHolder().setPrivateData(styleName,val);
+				modelChanged(ModelChange.STYLE_SELECTOR_CHANGED,0,this.textLength);
+			}
+		}
+		
+		private static const idString:String ="id";
+
+		/**
+		 * Assigns an identifying name to the element, making it possible to set a style for the element
+		 * by referencing the <code>id</code>. For example, the following line sets the color for
+		 * a SpanElement object that has an id of span1:
+		 *
+		 * <listing version="3.0" >
+		 * textFlow.getElementByID("span1").setStyle("color", 0xFF0000);
+		 * </listing>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see TextFlow#getElementByID()
+		 */
+		public function get id():String
+		{ return getPrivateStyle(idString); }
+		public function set id(val:String):void
+		{ return setPrivateStyle(idString, val);	}
+		
+		private static const styleNameString:String ="styleName";
+
+		/**
+		 * Assigns an identifying class to the element, making it possible to set a style for the element
+		 * by referencing the <code>styleName</code>. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get styleName():String
+		{ return getPrivateStyle(styleNameString); }
+		public function set styleName(val:String):void
+		{ return setPrivateStyle(styleNameString, val);	}
+		
+		private static const impliedElementString:String = "impliedElement";
+		/** @private */
+		tlf_internal function get impliedElement():Boolean
+		{
+			return getPrivateStyle(impliedElementString) !== undefined;
+		}
+		/** @private */		
+		tlf_internal function set impliedElement(value:Boolean):void
+		{
+			setPrivateStyle(impliedElementString, "true");
+		}
+				
+		// **************************************** 
+		// Begin TLFFormat Related code
+		// ****************************************
+		include "../formats/TextLayoutFormatInc.as"
+		
+		/** TextLayoutFormat properties applied directly to this element.
+		 * <p>Each element may have properties applied to it as part of its format. Properties applied to this element override properties inherited from the parent. Properties applied to this element will in turn be inherited by element's children if they are not overridden on the child. If no properties are applied to the element, this will be null.</p>
+		 * @see flashx.textLayout.formats.ITextLayoutFormat
+		 */
+		public function get format():ITextLayoutFormat
+		{ return _formatValueHolder; }
+		public function set format(value:ITextLayoutFormat):void
+		{
+			if (value == null)
+			{
+				if (_formatValueHolder == null || _formatValueHolder.coreStyles == null)
+					return; // no change
+				_formatValueHolder.coreStyles = null;
+			}
+			else
+				writableTextLayoutFormatValueHolder().format = value;
+			formatChanged();
+		}
+		
+		private function writableTextLayoutFormatValueHolder():FlowValueHolder
+		{
+			if (_formatValueHolder == null)
+				_formatValueHolder = new FlowValueHolder();
+			return _formatValueHolder;
+		}
+
+		/** This gets called when an element has changed its attributes. This may happen because an
+		 * ancestor element changed it attributes.
+		 * @private 
+		 */
+		tlf_internal function formatChanged(notifyModelChanged:Boolean = true):void
+		{
+			if (notifyModelChanged)
+				modelChanged(ModelChange.TEXTLAYOUT_FORMAT_CHANGED,0,textLength);
+			// wipe out whatever values were cached
+			_computedFormat = null;
+		}
+		
+		/** 
+		 * Concatenates tlf attributes with any other tlf attributes
+		 * 
+		 * Return the concatenated result
+		 * 
+		 * @private
+		 */
+		tlf_internal function get formatForCascade():ITextLayoutFormat
+		{
+			var tf:TextFlow = getTextFlow();
+			if (tf)
+			{
+				var elemStyle:ITextLayoutFormat  = tf.getTextLayoutFormatStyle(this);
+				if (elemStyle)
+				{
+					var localFormat:ITextLayoutFormat = format;
+					if (localFormat == null)
+						return elemStyle;
+						
+					var rslt:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+					rslt.apply(elemStyle);
+					rslt.apply(localFormat);
+					return rslt;
+				}
+			}
+			return format;
+		}
+		
+		/** @private  Shared scratch element for use in computedFormat methods only */
+		static tlf_internal var _scratchTextLayoutFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder();
+		
+		/** 
+		 * Returns the computed format attributes that are in effect for this element.
+		 * Takes into account the inheritance of attributes from parent elements.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		 */
+
+		public function get computedFormat():ITextLayoutFormat
+		{		
+			if (!_computedFormat)
+				doComputeTextLayoutFormat(formatForCascade);
+			return _computedFormat;
+		}
+		
+		/** @private */
+		tlf_internal function doComputeTextLayoutFormat(formatForCascade:ITextLayoutFormat):void
+		{
+			var element:FlowElement = parent;
+			var parentFormatForCascade:ITextLayoutFormat;
+			
+			if (element)
+			{
+				parentFormatForCascade = element.formatForCascade;
+				if (TextLayoutFormat.isEqual(formatForCascade,TextLayoutFormat.emptyTextLayoutFormat) && TextLayoutFormat.isEqual(parentFormatForCascade,TextLayoutFormat.emptyTextLayoutFormat))
+				{
+					_computedFormat = element.computedFormat;
+					return;
+				}
+			}
+			
+			var tf:TextFlow;
+			// compute the cascaded attributes	
+			_scratchTextLayoutFormat.format = formatForCascade;
+			if (element)
+			{
+				if (parentFormatForCascade)
+					_scratchTextLayoutFormat.concatInheritOnly(parentFormatForCascade);
+				while (element.parent)
+				{
+					element = element.parent;
+					var concatAttrs:ITextLayoutFormat = element.formatForCascade;
+					if (concatAttrs)
+						_scratchTextLayoutFormat.concatInheritOnly(concatAttrs);
+				}
+				tf = element as TextFlow;
+			}
+			else
+				tf = this as TextFlow;
+			var defaultFormat:ITextLayoutFormat;
+			var defaultFormatHash:uint;
+			if (tf)
+			{
+				defaultFormat = tf.getDefaultFormat();
+				defaultFormatHash = tf.getDefaultFormatHash();
+			}
+			_computedFormat = TextFlow.getCanonical(_scratchTextLayoutFormat,defaultFormat,defaultFormatHash);
+		}
+
+		// **************************************** 
+		// End CharacterFormat Related code
+		// ****************************************
+
+		
+		/** @private */
+		tlf_internal function attributesChanged(notifyModelChanged:Boolean = true):void
+		{
+			// TODO: REMOVE ME???
+			formatChanged(notifyModelChanged);
+		}
+		
+		/** Returns the value of the style specified by the <code>styleProp</code> parameter, which specifies
+		 * the style name and can include any user style name. Accesses an existing span, paragraph, text flow,
+		 * or container style. Searches the parent tree if the style's value is <code>undefined</code> on a 
+		 * particular element.
+		 *
+		 * @param styleProp The name of the style whose value is to be retrieved.
+		 *
+		 * @return The value of the specified style. The type varies depending on the type of the style being
+		 * accessed. Returns <code>undefined</code> if the style is not set.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_getStyleExample.as -noswf
+	 	 *
+	 	 * @see #clearStyle()
+		 * @see #setStyle()
+		 * @see #userStyles
+		 */
+		public function getStyle(styleProp:String):*
+		{
+			if (TextLayoutFormat.description.hasOwnProperty(styleProp))
+				return computedFormat[styleProp];
+			return getUserStyleWorker(styleProp);
+		}
+		
+		/** Sets the style specified by the <code>styleProp</code> parameter to the value specified by the
+		* <code>newValue</code> parameter. You can set a span, paragraph, text flow, or container style, including
+		* any user name-value pair.
+		*
+		* <p><strong>Note:</strong> If you assign a custom style, Text Layout Framework can import and export it but
+		* compiled MXML cannot support it.</p>
+		*
+		* @param styleProp The name of the style to set.
+		* @param newValue The value to which to set the style.
+		*.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @includeExample examples\FlowElement_setStyleExample.as -noswf
+		*		
+		* @see #clearStyle()
+		* @see #getStyle()
+		* @see #userStyles
+		*/
+		public function setStyle(styleProp:String,newValue:*):void
+		{
+			if (TextLayoutFormat.description[styleProp] !== undefined)
+				this[styleProp] = newValue;
+			else
+			{
+				writableTextLayoutFormatValueHolder().setUserStyle(styleProp,newValue);
+				modelChanged(ModelChange.USER_STYLE_CHANGED,0,this.textLength,true);
+			}
+		}
+		
+		/** Clears the style specified by the <code>styleProp</code> parameter from this FlowElement object. Sets 
+		 * the value to <code>undefined</code>.
+		 *
+		 * @param styleProp The name of the style to clear.
+		 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @includeExample examples\FlowElement_clearStyleExample.as -noswf
+		 *
+		 * @see #getStyle()
+		 * @see #setStyle()
+		 * @see #userStyles
+		 * 
+		 */
+		public function clearStyle(styleProp:String):void
+		{ setStyle(styleProp,undefined); }
+		
+		/** @private worker function - any styleProp */
+		tlf_internal function getUserStyleWorker(styleProp:String):*
+		{
+			CONFIG::debug { assert(TextLayoutFormat.description[styleProp] === undefined,"bad call to getUserStyleWorker"); }
+			
+			if (_formatValueHolder != null)
+			{
+				var userStyle:* = _formatValueHolder.getUserStyle(styleProp)
+				if (userStyle !== undefined)
+					return userStyle;
+			}
+				
+			var tf:TextFlow = getTextFlow();
+			if (tf && tf.formatResolver)
+			{
+				userStyle = tf.formatResolver.resolveUserFormat(this,styleProp);
+				if (userStyle !== undefined)
+					return userStyle;
+			}
+			// TODO: does TextFlow need to ask a "psuedo parent"				
+			return parent ? parent.getUserStyleWorker(styleProp) : undefined;
+		}
+		
+		/**
+		 * Called whenever the model is modified.  Updates the TextFlow and notifies the selection manager - if it is set.
+		 * This method has to be called while the element is still in the flow
+		 * @param changeType - type of change
+		 * @param start - elem relative offset of start of damage
+		 * @param len - length of damage
+		 * @see flow.model.ModelChange
+		 * @private
+		 */
+		tlf_internal function modelChanged(changeType:String, changeStart:int, changeLen:int, needNormalize:Boolean = true, bumpGeneration:Boolean = true):void
+		{
+			var tf:TextFlow = this.getTextFlow();
+			if (tf)
+				tf.processModelChanged(changeType, this, changeStart, changeLen, needNormalize, bumpGeneration);
+		}
+		
+		/** @private */
+		tlf_internal function appendElementsForDelayedUpdate(tf:TextFlow):void
+		{ }
+		
+		/** @private */
+		tlf_internal function applyDelayedElementUpdate(textFlow:TextFlow,okToUnloadGraphics:Boolean,hasController:Boolean):void
+		{ }
+						
+		// **************************************** 
+		// Begin display property Related code
+		// ****************************************
+		/**
+		 * Indicates how the element should be composed. It may be either inline, and appear as part of a line, or be float, 
+		 * in which case it appears in a container of its own.
+		 * 
+		 * @see text.elements.FlowElementDisplayType#INLINE
+		 * @see text.elements.FlowElementDisplayType#FLOAT
+		 * 
+		 * This feature still in prototype phase - has to be the main namespace so it is accessible through mxml
+		 * @private
+		 */
+		public function get display():String
+		{
+			return FlowElementDisplayType.INLINE;
+		}
+		
+		// **************************************** 
+		// End display property Related code
+		// ****************************************	
+
+ 		// **************************************** 
+		// Begin tracking property Related code
+		// ****************************************
+
+		/**
+		 * Sets the tracking and is synonymous with the <code>trackingRight</code> property. Specified as a number of
+		 * pixels or a percent of <code>fontSize</code>.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #trackingRight
+		 */
+		public function set tracking(trackingValue:Object):void
+		{
+			trackingRight = trackingValue;
+		}
+		
+		// **************************************** 
+		// End tracking property Related code
+		// ****************************************	
+
+		// **************************************** 
+		// Begin import helper code
+		// ****************************************			
+
+		/**
+		 *  @private Create the default container for the element.
+		 */
+		tlf_internal function createGeometry(parentToBe:DisplayObjectContainer):void
+		{
+			return;
+		}
+		
+		/** Strips white space from the element and its children, according to the whitespaceCollaspse
+		 *  value that has been applied to the element or inherited from its parent.
+		 *  If a FlowLeafElement's attrs are set to WhiteSpaceCollapse.PRESERVE, then collapse is
+		 *  skipped.
+		 *  @see text.formats.WhiteSpaceCollapse
+		 * @private 
+		 */
+		tlf_internal function applyWhiteSpaceCollapse():void
+		{
+			if (_formatValueHolder && _formatValueHolder.whiteSpaceCollapse !== undefined)
+				whiteSpaceCollapse = undefined;
+			
+			setPrivateStyle(impliedElementString, undefined);
+		}
+				
+		// **************************************** 
+		// End import helper code
+		// ****************************************	
+
+		// **************************************** 
+		// Begin helper code for tables
+		// ****************************************			
+		
+		/** Determines whether a particular FlowElement should be treated as a single selection.
+		 * @private
+		 */
+		tlf_internal function isReadOnlyFlowElement():Boolean
+		{
+			return false;
+		}
+
+		/** Gets the highest parent that is a read only flow element
+		 * @private
+		 */		
+		tlf_internal function getHighestReadOnlyFlowElement():FlowElement
+		{
+			var highestReadOnlyFlowElement:FlowElement = null;
+			if (this.isReadOnlyFlowElement())
+			{
+				highestReadOnlyFlowElement = this;
+			}
+			
+			var curFlowElement:FlowElement = parent;
+			while (curFlowElement != null)
+			{
+				if (curFlowElement.isReadOnlyFlowElement())
+				{
+					highestReadOnlyFlowElement = curFlowElement;
+				}
+				curFlowElement = curFlowElement.parent;
+			}
+			return highestReadOnlyFlowElement;
+		}
+		
+		// **************************************** 
+		// End helper code for tables
+		// ****************************************							
+
+		// **************************************** 
+		// Begin tree navigation code
+		// ****************************************
+		
+		 /**
+		 * Returns the start location of the element in the text flow as an absolute index. The first character in the flow
+		 * is position 0.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 * 
+		 * @includeExample examples\FlowElement_getAbsoluteStartExample.as -noswf
+		 *
+ 		 * @return The index of the start of the element from the start of the TextFlow object.
+ 		 *
+ 		 * @see #parentRelativeStart
+ 		 * @see TextFlow
+	 	 */
+	 	 
+		public function getAbsoluteStart():int
+		{
+			var rslt:int = parentRelativeStart;
+			for (var elem:FlowElement = parent; elem; elem = elem.parent)
+				rslt += elem.parentRelativeStart;
+			return rslt;
+		}
+		
+		/**
+		 * Returns the start of this element relative to an ancestor element. Assumes that the
+		 * ancestor element is in the parent chain. If the ancestor element is the parent, this is the
+		 * same as <code>this.parentRelativeStart</code>.  If the ancestor element is the grandparent, this is the same as 
+		 * <code>parentRelativeStart</code> plus <code>parent.parentRelativeStart</code> and so on.
+		 * 
+		 * @param ancestorElement The element from which you want to find the relative start of this element.
+		 *
+		 * @return  the offset of this element.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_getElementRelativeStartExample.as -noswf
+		 * 
+		 * @see #getAbsoluteStart()
+		 */
+		 
+		public function getElementRelativeStart(ancestorElement:FlowElement):int
+		{
+			var rslt:int = parentRelativeStart;
+			for (var elem:FlowElement = parent; elem && elem != ancestorElement; elem = elem.parent)
+				rslt += elem.parentRelativeStart;
+			return rslt;
+		}
+		
+		/**
+		 * Climbs the text flow hierarchy to return the root TextFlow object for the element.
+		 *
+		 * @return	The root TextFlow object for this FlowElement object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_getTextFlowExample.as -noswf
+	 	 *
+	 	 * @see TextFlow
+		 */
+		 
+		public function getTextFlow():TextFlow
+		{
+			// find the root element entry and either return null or the containing textFlow
+			var elem:FlowElement = this;
+			while (elem.parent != null)
+				elem = elem.parent;
+			return elem as TextFlow;		
+		}	
+
+		/**
+		 * Returns the ParagraphElement object associated with this element. It looks up the text flow hierarchy and returns 
+		 * the first ParagraphElement object.
+		 *
+		 * @return	the ParagraphElement object that's associated with this FlowElement object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples\FlowElement_getParagraphExample.as -noswf
+	 	 * 
+	 	 * @see #getTextFlow()
+	 	 * @see ParagraphElement
+		 */
+		 
+		public function getParagraph():ParagraphElement
+		{
+			var rslt:FlowElement = this;
+			while (rslt)
+			{
+				if (rslt is ParagraphElement)
+					return rslt as ParagraphElement;
+				rslt = rslt.parent;
+			}
+			return null;
+		}
+		
+		
+		/** 
+		 * Returns the FlowElement object that contains this FlowElement object, if this element is contained within 
+		 * an element of a particular type. 
+		 * 
+		 * Returns the FlowElement it is contained in. Otherwise, it returns null.
+		 * 
+		 * @private
+		 *
+		 * @param elementType	type of element for which to check
+		 */
+		public function getParentByType(elementType:Class):FlowElement
+		{
+			var curElement:FlowElement = parent;
+			while (curElement)
+			{
+				if (curElement is elementType)
+					return curElement;
+				curElement = curElement.parent;
+			}
+			return null;
+		}
+		
+		/** Returns the previous FlowElement sibling in the text flow hierarchy. 
+		*
+		* @includeExample examples\FlowElement_getPreviousSiblingExample.as -noswf
+		*
+		* @return 	the previous FlowElement object of the same type, or null if there is no previous sibling.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see #getNextSibling()
+		*/
+		public function getPreviousSibling():FlowElement
+		{
+			//this can happen if FE is on the scrap and doesn't have a parent. - gak 06.25.08
+			if(!parent)
+				return null;
+				
+			var idx:int = parent.getChildIndex(this);
+			return idx == 0 ? null : parent.getChildAt(idx-1);
+		}
+		
+		/** Returns the next FlowElement sibling in the text flow hierarchy. 
+		*
+		* @return the next FlowElement object of the same type, or null if there is no sibling.
+		*
+		* @includeExample examples\FlowElement_getNextSiblingExample.as -noswf
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see #getPreviousSibling()
+	 	*/
+	 	
+		public function getNextSibling():FlowElement
+		{
+			if (!parent)
+				return null;
+
+			var idx:int = parent.getChildIndex(this);
+			return idx == parent.numChildren-1 ? null : parent.getChildAt(idx+1);
+		}
+		
+		/** 
+		* Returns the character at the specified position, relative to this FlowElement object. The first
+		* character is at relative position 0.
+		* 
+		* @param relativePosition	The relative position of the character in this FlowElement object.
+		* @return String containing the character.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @includeExample examples\FlowElement_getCharAtPositionExample.as -noswf
+	 	* 
+	 	* @see #getCharCodeAtPosition()
+	 	*/
+		
+		public function getCharAtPosition(relativePosition:int):String
+		{
+			return null;
+		}
+		
+		/** Returns the character code at the specified position, relative to this FlowElement. The first
+		* character is at relative position 0.
+		*
+		* @param relativePosition 	The relative position of the character in this FlowElement object.
+		*
+		* @return	the Unicode value for the character at the specified position.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @includeExample examples\FlowElement_getCharCodeAtPositionExample.as -noswf
+	 	*
+	 	* @see #getCharAtPosition()
+	 	*/
+	 	
+		public function getCharCodeAtPosition(relativePosition:int):int
+		{
+			var str:String = getCharAtPosition(relativePosition);
+			return str && str.length > 0 ? str.charCodeAt(0) : 0;
+		}
+		
+		/** @private return an element or matching idName. */
+		tlf_internal function getElementByIDHelper(idName:String):FlowElement
+		{
+			if (this.id == idName)
+				return this;
+			return null;
+		}
+		
+		/** @private return adding elements with matching styleName to an array. */
+		tlf_internal function getElementsByStyleNameHelper(a:Array,styleName:String):void
+		{
+			if (this.styleName == styleName)
+				a.push(this);
+		}
+		
+		// **************************************** 
+		// End tree navigation code
+		// ****************************************	
+		
+		// **************************************** 
+		// Begin tree modification support code
+		// ****************************************	
+
+		/**
+		 * Update the FlowElement to account for text added before it.
+		 *
+		 * @param len	number of characters added (may be negative if deletion)
+		 */
+		private function updateRange(len:int): void
+		{
+			setParentRelativeStart(parentRelativeStart + len);
+		}
+		
+		/** Update the FlowElements in response to an insertion or deletion.
+		 *  The length of the element inserted to is updated, and the length of 
+		 *  each of its ancestor element. Each of the elements following siblings
+		 *  start index is updated (start index is relative to parent).
+		 * @private
+		 * @param startIdx		absolute index in flow where text was inserted
+		 * @param len			number of characters added (negative if removed)
+		 * updateLines			?? true if lines should be damaged??
+		 * @private 
+		 */
+		tlf_internal function updateLengths(startIdx:int,len:int,updateLines:Boolean):void
+		{
+			setTextLength(textLength + len);		
+			var p:FlowGroupElement = parent;	
+			if (p)
+			{
+				// update the elements following this in parent's children				
+				var idx:int = p.getChildIndex(this)+1;
+				CONFIG::debug { assert(idx != -1,"bad parent in FlowElement.updateLengths"); }
+				
+				var pElementCount:int = p.numChildren;
+				while (idx < pElementCount)
+				{
+					var child:FlowElement = p.getChildAt(idx++);
+					child.updateRange(len);
+				}
+				
+				// go up the tree to the root and update ancestor's lengths
+				p.updateLengths(startIdx,len,updateLines);
+			}
+		}
+		
+		/** @private */
+		tlf_internal function getEnclosingController(relativePos:int) : ContainerController
+		{
+			// CONFIG::debug { assert(pos <= length,"getEnclosingController - bad pos"); }
+			
+			var textFlow:TextFlow = getTextFlow();
+			
+			//more than likely, we are building up spans for the very first time.
+			//the container has not yet been created
+			if (textFlow == null || textFlow.flowComposer == null || textFlow.flowComposer.numLines == 0)
+				return null;
+			
+			var curItem:FlowElement = this;
+			while (curItem && (!(curItem is ContainerFormattedElement) || ContainerFormattedElement(curItem).flowComposer == null))
+			{
+				curItem = curItem.parent;
+			}
+			
+			var flowComposer:IFlowComposer = ContainerFormattedElement(curItem).flowComposer;
+			if (!flowComposer)
+				return null;
+				
+			var controllerIndex:int = ContainerFormattedElement(curItem).flowComposer.findControllerIndexAtPosition(getAbsoluteStart() + relativePos,false);
+			return controllerIndex != -1 ? flowComposer.getControllerAt(controllerIndex) : null;
+		}
+
+		
+		/** @private */
+		tlf_internal function deleteContainerText(endPos:int,deleteTotal:int):void
+		{
+			// update container counts
+					
+			if (getTextFlow())		// update container lengths only for elements that are attached to the rootElement
+			{
+				var absoluteEndPos:int = getAbsoluteStart() + endPos;
+				var absStartIdx:int = absoluteEndPos-deleteTotal;
+				
+				while (deleteTotal > 0)
+				{
+					var charsDeletedFromCurContainer:int;
+					var enclosingController:ContainerController = getEnclosingController(endPos-1);
+					if (!enclosingController)
+					{
+						// The end of the deleted text may be overset, so it doesn't appear in a container.
+						// Find the last container that contains the deleted text.
+						enclosingController = getEnclosingController(endPos - deleteTotal);
+						if (enclosingController)
+						{
+							var flowComposer:IFlowComposer = enclosingController.flowComposer;
+							var myIdx:int = flowComposer.getControllerIndex(enclosingController);
+							CONFIG::debug { assert(myIdx >= 0,"FlowElement.deleteContainerText: bad return from getContainerControllerIndex"); }
+							while (myIdx+1 < flowComposer.numControllers && enclosingController.absoluteStart + enclosingController.textLength < endPos)
+							{
+								enclosingController = flowComposer.getControllerAt(myIdx+1);
+								if (enclosingController.textLength)
+									break;
+								myIdx++;
+							}
+						}
+						if (!enclosingController)
+							break;
+					}
+					var enclosingControllerBeginningPos:int = enclosingController.absoluteStart;
+					if (absStartIdx < enclosingControllerBeginningPos)
+					{
+						charsDeletedFromCurContainer = absoluteEndPos - enclosingControllerBeginningPos + 1;
+					}
+					else if (absStartIdx < enclosingControllerBeginningPos + enclosingController.textLength)
+					{
+						charsDeletedFromCurContainer = deleteTotal;
+					} 
+					// Container textFlowLength may contain fewer characters than the those to be deleted in case of overset text. 
+					var containerTextLengthDelta:int = enclosingController.textLength < charsDeletedFromCurContainer ? enclosingController.textLength : charsDeletedFromCurContainer;
+					if (containerTextLengthDelta <= 0)
+						break;		// overset text is not in the last container -- we've deleted the container count, so exit
+					// working backwards - can't call setTextLength as it examines previous controllers and gets confused in the composeCompleteRatio logic
+					ContainerController(enclosingController).setTextLengthOnly(enclosingController.textLength -  containerTextLengthDelta);
+					deleteTotal -= containerTextLengthDelta;
+					absoluteEndPos -= containerTextLengthDelta;
+					endPos -= containerTextLengthDelta;
+				}
+			}
+		}
+		
+		/** @private */
+		tlf_internal function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			// default is do nothing
+		}
+		
+		/** Support for splitting FlowLeafElements.  Does a quick copy of _characterFormat if necessary.  @private */
+		tlf_internal function quickCloneTextLayoutFormat(sibling:FlowElement):void
+		{
+			_formatValueHolder = sibling._formatValueHolder ? new FlowValueHolder(sibling._formatValueHolder) : null;
+		}
+			
+		// **************************************** 
+		// End tree modification support code
+		// ****************************************	
+		
+		/** @private This API supports the inputmanager */
+		tlf_internal function updateForMustUseComposer(textFlow:TextFlow):Boolean
+		{ return false; }
+
+		// **************************************** 
+		// Begin debug support code
+		// ****************************************	
+		
+		CONFIG::debug static private var debugDictionary:Dictionary = new Dictionary(true);
+		CONFIG::debug static private var nextKey:int = 1;
+		
+		CONFIG::debug static public function getDebugIdentity(o:Object):String
+		{
+			if (debugDictionary[o] == null)
+			{
+				var s:String = flash.utils.getQualifiedClassName(o);
+				if (s)
+					s = s.substr( s.lastIndexOf(":")+1);
+				else
+					s = "";
+				debugDictionary[o] = s + "." + nextKey.toString();
+				nextKey++;
+			}
+			return debugDictionary[o];
+		}
+		
+		/**
+		 * Check FlowElement for internal consistency.
+		 * @private
+		 * Lots of internal checks are done on FlowElements, some are dependent
+		 * on the type of element. 
+		 * @return Number of errors found
+		 */
+		CONFIG::debug public function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			if (Debugging.verbose)
+			{			
+				if (depth == 0)
+					trace("----------------------------------");
+
+				trace("FlowElement:",depth.toString(),getDebugIdentity(this),"start:",parentRelativeStart.toString(),"length:",textLength.toString(),extraData);
+			}
+			return 0;
+		}
+		
+		CONFIG::debug public static function elementPath(element:FlowElement):String
+		{
+			var result:String;
+			
+			if (element != null)
+			{
+				if (element.parent != null)
+					result = elementPath(element.parent) + "." + element.name + "[" + element.parent.getChildIndex(element) + "]";
+				else
+					result = element.name;
+			}
+			return result;
+		}
+
+		/**
+		 * debugging only - show element as string
+		 */
+		CONFIG::debug public function toString():String
+		{
+			return "flowElement:" + name + " start:" + parentRelativeStart.toString() + " absStart:" + this.getAbsoluteStart().toString() + " textLength:" + textLength.toString();			
+		}
+		// **************************************** 
+		// End debug support code
+		// ****************************************	
+
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/FlowGroupElement.as b/textLayout_core/src/flashx/textLayout/elements/FlowGroupElement.as
new file mode 100755
index 0000000..1f9c889
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/FlowGroupElement.as
@@ -0,0 +1,1165 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements 
+{
+	import flash.display.DisplayObjectContainer;
+	import flash.text.engine.ContentElement;
+	import flash.text.engine.GroupElement;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.FlowDamageType;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[DefaultProperty("mxmlChildren")]
+
+	/** 
+	 * The FlowGroupElement class is the base class for FlowElement objects that can have an array of children. These classes include
+	 * TextFlow, ParagraphElement, DivElement, and LinkElement.
+	 *
+	 * <p>You cannot create a FlowGroupElement object directly. Invoking <code>new FlowGroupElement()</code> throws an error 
+ 	 * exception.</p>
+ 	 *
+ 	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see DivElement
+	 * @see LinkElement
+	 * @see ParagraphElement
+	 * @see TextFlow
+	 */ 
+	public class FlowGroupElement extends FlowElement
+	{
+		/** children of the FlowGroupElement.  They must all be FlowElements. Depending on _numChildren either store a single child in _singleChild or multiple children in the array. */
+		private var _childArray:Array;
+		private var _singleChild:FlowElement;
+		private var _numChildren:int;
+		
+		/** Base class - invoking <code>new FlowGroupElement()</code> throws an error exception.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function FlowGroupElement()
+		{
+			_numChildren = 0;
+		}
+		
+		/** @private */
+		public override function deepCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			if (endPos == -1)
+				endPos = textLength;
+				
+			var retFlow:FlowGroupElement = shallowCopy(startPos, endPos) as FlowGroupElement;
+			var newFlowElement:FlowElement;
+			for (var idx:int = 0; idx < _numChildren; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				if (((startPos - child.parentRelativeStart) < child.textLength) && ((endPos - child.parentRelativeStart) > 0))			
+				{
+					//child is in Selected area
+					newFlowElement = child.deepCopy(startPos - child.parentRelativeStart, endPos - child.parentRelativeStart);
+					retFlow.replaceChildren(retFlow.numChildren,retFlow.numChildren,newFlowElement);	
+					if (retFlow.numChildren > 1)
+					{
+						var possiblyEmptyFlowElement:FlowElement = retFlow.getChildAt(retFlow.numChildren - 2);
+						if (possiblyEmptyFlowElement.textLength == 0)
+						{
+							retFlow.replaceChildren(retFlow.numChildren - 2, retFlow.numChildren - 1);
+						}
+					}									
+				}
+			}
+			return retFlow;
+		}
+		
+		/* @private */
+		public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+		{
+			var text:String = super.getText();
+			
+			if (relativeEnd == -1)
+				relativeEnd = textLength;
+
+			var pos:int = relativeStart;
+			for (var idx:int = findChildIndexAtPosition(relativeStart); idx < _numChildren && pos < relativeEnd; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				var copyStart:int = pos - child.parentRelativeStart;
+				var copyEnd:int = Math.min(relativeEnd - child.parentRelativeStart, child.textLength);
+				text += child.getText(copyStart, copyEnd, paragraphSeparator);
+				pos += copyEnd - copyStart;
+				if (paragraphSeparator && child is ParagraphFormattedElement && pos < relativeEnd)
+					text += paragraphSeparator;
+			}
+			return text;
+		}
+		
+		// **************************************** 
+		// Begin TextLayoutFormat Related code
+		// ****************************************
+		/** @private */
+		tlf_internal override function formatChanged(notifyModelChanged:Boolean = true):void
+		{
+			super.formatChanged(notifyModelChanged);
+			for (var idx:int = 0; idx < _numChildren; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				child.formatChanged(false);
+			}			
+		}
+		// **************************************** 
+		// End TLFFormat Related code
+		// ****************************************
+	
+		// **************************************** 
+		// Begin import helper code 
+		// ****************************************	
+		[RichTextContent]
+		/** 
+		 * Appends an array of children to this object. Uses the <code>replaceChildren()</code> method to append each 
+		 * element in the array. Intended for use during an mxml compiled import.
+		 * 
+		 * @throws TypeError if array element is not a FlowElement or String
+		 * @param array - array of children to attach.  Each element of the array must be a FlowElement object or a String.
+		 * @see FlowGroupElement#replaceChildren()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get mxmlChildren():Array
+		{
+			return _numChildren == 0 ? null : (_numChildren == 1 ? [ this._singleChild ] : _childArray.slice() );
+		}
+		public function set mxmlChildren(array:Array):void
+		{
+			/* NOTE: all FlowElement implementers and overrides of mxmlChildren must specify [RichTextContent] metadata */
+
+			// remove all existing children
+			this.replaceChildren(0,_numChildren);
+			
+			// In the text model, non-ParagraphFormattedElements (i.e. spans, images, links, TCY) cannot be children of a ContainerFormattedElement (TextFlow, DivElement etc.)
+			// They can only be children of paragraphs or subparagraph blocks. 
+			// In XML, however, <p> elements can be implied (for example, a <span> may appear as a direct child of <flow>).  
+			// So, while parsing the XML, if we enounter a non-ParagraphFormattedElement child of a ContainerFormattedElement 
+			// 1. an explicitly created paragraph is used as the parent instead
+			// 2. such explicitly created paragraphs are shared by adjacent flow elements provided there isn't an intervening ParagraphFormattedElement
+			var effectiveParent:FlowGroupElement = this; 
+			
+			// append them on the end		
+			for each (var child:Object in array)
+			{
+				if (child is FlowElement)
+				{
+					if (child is ParagraphFormattedElement)
+					{
+						// Reset due to possibly intervening FlowParagrpahElement; See note 2. above
+						effectiveParent = this; 
+					}
+					else if (effectiveParent is ContainerFormattedElement)
+					{
+						// See note 1. above
+						effectiveParent = new ParagraphElement();
+						effectiveParent.impliedElement = true;
+						replaceChildren(_numChildren, _numChildren, effectiveParent);
+					}
+					if ( (child is SpanElement) || (child is SubParagraphGroupElement))
+						child.bindableElement = true;
+					effectiveParent.replaceChildren(effectiveParent.numChildren, effectiveParent.numChildren, FlowElement(child) );
+				}
+				else if (child is String)
+				{
+					var s:SpanElement = new SpanElement();
+					s.text = String(child);
+					s.bindableElement = true;
+					s.impliedElement = true;
+					
+					if (effectiveParent is ContainerFormattedElement)
+					{
+						// See note 1. above
+	 					effectiveParent = new ParagraphElement();
+						replaceChildren(_numChildren, _numChildren, effectiveParent);
+						effectiveParent.impliedElement = true;
+					}
+					effectiveParent.replaceChildren(effectiveParent.numChildren, effectiveParent.numChildren, s);
+				}
+				else if (child != null)
+					throw new TypeError(GlobalSettings.resourceStringFunction("badMXMLChildrenArgument",[ getQualifiedClassName(child) ]));
+			}
+		}
+
+		/** @private */
+		override tlf_internal function createGeometry(parentToBe:DisplayObjectContainer):void
+		{
+			for (var idx:int = 0; idx < _numChildren; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				child.createGeometry(parentToBe);
+			}
+		}
+				
+		// **************************************** 
+		// End import helper code
+		// ****************************************	
+		// **************************************** 
+		// Begin tree navigation code
+		// ****************************************	
+		
+		/** 
+		* Returns the number of FlowElement children that this FlowGroupElement object has.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function get numChildren(): int
+		{
+			return _numChildren;
+		}
+		
+		/** 
+		 * Searches in children for the specified FlowElement object and returns its index position.
+		 *
+		 * @param child	The FlowElement object item to locate among the children.
+		 * @return The index position of the specified chilc.  If <code>child</code> is not found, returns -1.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function getChildIndex(child:FlowElement):int
+		{
+			var hi:int = _numChildren-1;
+			// one hole here - if child is null and this has no children then we'll return 0
+			if (hi <= 0)
+				return _singleChild == child ? 0 : -1;
+			
+			var lo:int = 0;
+			while (lo <= hi)
+			{
+				var mid:int = (lo+hi)/2;
+				var p:FlowElement = _childArray[mid];
+				if (p.parentRelativeStart == child.parentRelativeStart)
+				{
+					// during intermediate caluclations there are zero length elements lurking about
+					if (p == child)
+					{
+						CONFIG::debug { assert(_childArray.indexOf(child) == mid,"Bad getChildIndex"); }
+						return mid;
+					}
+					var testmid:int;
+					if (p.textLength == 0)
+					{
+						// look forward for a match
+						for (testmid = mid; testmid < _numChildren; testmid++)
+						{
+							p = _childArray[testmid];
+							if (p == child)
+							{
+								CONFIG::debug { assert(_childArray.indexOf(child) == testmid,"Bad getChildIndex"); }
+								return testmid;
+							}
+							if (p.textLength != 0)
+								break;
+						}
+					}
+					
+					// look backwards
+					while (mid > 0)
+					{
+						mid--;
+						p = _childArray[mid];
+						if (p == child)
+						{
+							CONFIG::debug { assert(_childArray.indexOf(child) == mid,"Bad getChildIndex"); }
+							return mid;
+						}
+						if (p.textLength != 0)
+							break;
+					}
+					CONFIG::debug { assert(_childArray.indexOf(child) == -1,"Bad getChildIndex"); }
+					return -1;
+				}
+				if (p.parentRelativeStart < child.parentRelativeStart)
+					lo = mid+1;
+				else
+					hi = mid-1;
+			}
+			CONFIG::debug { assert(_childArray.indexOf(child) == -1,"Bad getChildIndex"); }
+			return -1;
+		}
+		/** 
+		 * Returns the FlowElement child at the specified index.
+		 * 
+		 * @param index the position at which to find the FlowElement object.
+		 *
+		 * @return  the child FlowElement object at the specified position.
+		 * @includeExample examples\FlowGroupElement_getChildAtExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function getChildAt(index:int):FlowElement
+		{
+			if (_numChildren > 1)
+				return _childArray[index];
+			return index == 0 ? _singleChild : null;
+		}
+	
+		/** @private */
+		tlf_internal function getNextLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+		{
+			var idx:int = getChildIndex(child);
+			if (idx == -1)
+				return null;	// bug?
+			
+			if (idx == _numChildren-1)
+			{
+				if (limitElement == this || !parent)
+					return null;
+				
+				return parent.getNextLeafHelper(limitElement,this);
+			}
+			
+			var child:FlowElement = getChildAt(idx+1);
+			return (child is FlowLeafElement) ? FlowLeafElement(child) : FlowGroupElement(child).getFirstLeaf();
+		}
+				
+		/** @private */
+		tlf_internal function getPreviousLeafHelper(limitElement:FlowGroupElement,child:FlowElement):FlowLeafElement
+		{
+			var idx:int = getChildIndex(child);
+			if (idx == -1)
+				return null;	// bug?
+			
+			if (idx == 0)
+			{
+				if (limitElement == this || !parent)
+					return null;
+				
+				return parent.getPreviousLeafHelper(limitElement,this);
+			}
+			
+			var child:FlowElement = getChildAt(idx-1);
+			return (child is FlowLeafElement) ? FlowLeafElement(child) : FlowGroupElement(child).getLastLeaf();
+		}
+	
+		/**
+		 * Given a relative text position, find the leaf element that contains the position. 
+		 *
+		 * <p>Looks down the flow element hierarchy to find the FlowLeafElement that 
+		 * contains the specified position. The specified position 
+		 * is relative to this FlowElement object.</p>
+		 *
+		 * @param relativePosition	relative text index to look up.
+		 * @return	the leaf element containing the relative position.
+		 *
+		 * @includeExample examples\FlowGroupElement_findLeafExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function findLeaf(relativePosition:int):FlowLeafElement
+		{
+			var found:FlowLeafElement = null;
+			var childIdx:int = findChildIndexAtPosition(relativePosition);
+			if (childIdx != -1)
+			{
+				// childIdx is index of the first child containing pos. Many of its following siblings
+				// may also contain pos if their respective previous siblings are zero-length. 
+				// Check them all until a leaf containing pos is found.
+				do
+				{
+					var child:FlowElement = this.getChildAt(childIdx++);
+					if (!child)
+						break;
+					
+					var childRelativePos: int = relativePosition - child.parentRelativeStart;
+					if (child is FlowGroupElement)
+						found = FlowGroupElement(child).findLeaf(childRelativePos);
+					else
+					{
+						// if its not a FlowGroupElement than it must be a FlowLeafElement
+						CONFIG::debug { assert(child is FlowLeafElement,"Invalid child in FlowGroupElement.findLeaf"); }
+						if (childRelativePos >= 0 && childRelativePos < child.textLength || (child.textLength == 0 && _numChildren == 1))
+							found = FlowLeafElement(child);
+					}
+				} while (!found && !child.textLength);
+				
+			}
+			return found;
+		}
+		
+		/**
+		 * Given a relative text position, find the index of the first child FlowElement that contains the relative position. 
+		 * More than one child can contain relative position because of zero length FlowElements.
+		 *  
+		 * <p>Examine the children to find the FlowElement that contains the relative position. The supplied relative position 
+		 * is relative to this FlowElement.</p>
+		 *
+		 * @param relativePosition 	the position relative to this element
+		 * @return 	index of first child element containing <code>relativePosition</code>
+		 *
+		 * @includeExample examples\FlowGroupElement_findChildIndexAtPositionExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function findChildIndexAtPosition(relativePosition:int):int
+		{
+			var lo:int = 0;
+			var hi:int = _numChildren-1;
+			while (lo <= hi)
+			{
+				var mid:int = (lo+hi)/2;
+				var child:FlowElement = getChildAt(mid);
+				if (child.parentRelativeStart <= relativePosition)
+				{
+					// always return the first zero length element in the list
+					if (child.parentRelativeStart == relativePosition)
+					{
+						while (mid != 0)
+						{
+							child = getChildAt(mid-1);
+							if (child.textLength != 0)
+								break;
+							mid--;
+						}
+						return mid;
+					}
+					if (child.parentRelativeStart + child.textLength > relativePosition)
+						return mid;
+					lo = mid+1;
+				}
+				else
+					hi = mid-1;
+			}
+			return -1;
+		}
+		
+		/**
+		 * Returns the first FlowLeafElement descendant of this group.
+		 *
+		 * @return the first FlowLeafElement object.
+		 *
+		 * @includeExample examples\FlowGroupElement_getFirstLeafExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function getFirstLeaf(): FlowLeafElement
+		{
+			if (_numChildren > 1)
+			{
+				for (var idx:int = 0; idx < _numChildren; idx++)
+				{
+					var child:FlowElement = _childArray[idx];
+					var leaf:FlowLeafElement = (child is FlowGroupElement) ? FlowGroupElement(child).getFirstLeaf() : FlowLeafElement(child);
+					if (leaf)
+						return leaf;
+				}
+				return null;
+			}
+			return _numChildren == 0 ? null : ((_singleChild is FlowGroupElement) ? FlowGroupElement(_singleChild).getFirstLeaf() : FlowLeafElement(_singleChild));
+		}
+		
+		/**
+		 * Returns the last FlowLeafElement descendent of this group.
+		 *
+		 * @return the last FlowLeafElement object.
+		 *
+		 * @includeExample examples\FlowGroupElement_getLastLeafExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function getLastLeaf(): FlowLeafElement
+		{
+			if (_numChildren > 1)
+			{
+				for (var idx:int = _numChildren; idx != 0; idx--)
+				{
+					var child:FlowElement = _childArray[idx-1];
+					var leaf:FlowLeafElement = (child is FlowGroupElement) ? FlowGroupElement(child).getLastLeaf() : FlowLeafElement(child) ;
+					if (leaf)
+						return leaf;
+				}
+				return null;
+			}
+			return _numChildren == 0 ? null : ((_singleChild is FlowGroupElement) ? FlowGroupElement(_singleChild).getLastLeaf() : FlowLeafElement(_singleChild));
+		}
+		
+		/** @private */
+		public override function getCharAtPosition(relativePosition:int):String
+		{
+			var leaf:FlowLeafElement = findLeaf(relativePosition);
+			return leaf ? leaf.getCharAtPosition(relativePosition-leaf.getElementRelativeStart(this)) : "";
+		} 
+		
+		/** @private return an element or matching idName. */
+		tlf_internal override function getElementByIDHelper(idName:String):FlowElement
+		{
+			var rslt:FlowElement = super.getElementByIDHelper(idName);
+			if (rslt == null)
+			{
+				for (var idx:int = 0; idx < _numChildren; idx++)
+				{
+					var child:FlowElement = getChildAt(idx);
+					rslt = child.getElementByIDHelper(idName);
+					if (rslt != null)
+						break;
+				}
+			}
+			return rslt;
+		}
+		
+		/** @private return adding elements with matching styleName to an array. */
+		tlf_internal override function getElementsByStyleNameHelper(a:Array,styleName:String):void
+		{
+			super.getElementsByStyleNameHelper(a,styleName);
+			for (var idx:int = 0; idx < _numChildren; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				child.getElementsByStyleNameHelper(a,styleName);
+			}
+
+		}
+		// **************************************** 
+		// End tree navigation code
+		// ****************************************			
+		// **************************************** 
+		// Begin tree modification support code
+		// ****************************************	
+		
+		/** @private */
+		tlf_internal function removeBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			// when Image's are moved into ParagraphElement's this assertion should always fire
+			CONFIG::debug { assert(child is InlineGraphicElement,"invalid call to removeBlockElement"); }
+		}
+		
+		/** @private */
+		tlf_internal function insertBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			// when Image's are moved into ParagraphElement's this assertion should always fire
+			CONFIG::debug { assert(child is InlineGraphicElement,"invalid call to insertBlockElement"); }
+		}
+		
+		/** @private 
+		 * True if there is a corresponding FTE data structure currently instantiated.
+		 */
+		tlf_internal function hasBlockElement():Boolean
+		{
+			CONFIG::debug { assert(false,"invalid call to hasBlockElement"); }
+			return false;
+		}
+		
+		/** @private */
+		tlf_internal function createContentAsGroup():GroupElement
+		{
+			CONFIG::debug { assert(false,"invalid call to createContentAsGroup"); }
+			return null;
+		}
+				
+		/** @private This is only called from SpanElement.splitAtPosition */
+		tlf_internal function addChildAfterInternal(child:FlowElement, newChild:FlowElement):void
+		{
+			//this function was kept for efficiency purposes. It is used by splitForChange
+			//which in turn is used by applyCharacterFormat, when changing the
+			//attributes applied to characters.  In the end, the length of the document
+			//will be the same. So, without this fnction, we would be creating a new
+			//span, updating the lengths, and then removing a part of the span and updating
+			//the lengths again (getting the same exact lengths we had before). This can be
+			//inefficient. So, this function does everything addChildAfter does, without
+			//updating the lengths. This is an internal function since the user really has
+			//to know what they're doing and will not be exposed as a public API
+			CONFIG::debug { assert(_numChildren != 0, "addChildAfter must have children"); }
+			CONFIG::debug { assert(getChildIndex(child) != -1, "addChildAfter: before child must be in array"); }
+			if (_numChildren > 1)
+			{
+				// TODO: binary search for indexOf child
+				CONFIG::debug { assert(_childArray.indexOf(child) != -1,"Bad call to addChildAfterInternal"); }
+				_childArray.splice(_childArray.indexOf(child)+1,0,newChild);
+			}
+			else
+			{
+				// not found returns above returns -1 so behave the same
+				CONFIG::debug { assert(_singleChild == child,"Bad call to addChildAfterInternal"); }
+				_childArray = [ _singleChild, newChild ];
+				_singleChild = null;
+			}
+			_numChildren++;
+			newChild.setParentAndRelativeStartOnly(this,child.parentRelativeEnd);
+		}
+		
+		/**
+		 * Helper for replaceChildren.  Determines if elem can legally be a child of this.
+		 * @return true --> ok, false--> not a legal child
+		 * @private 
+		 */
+		tlf_internal function canOwnFlowElement(elem:FlowElement):Boolean
+		{
+			return !(elem is TextFlow) && !(elem is FlowLeafElement) && !(elem is SubParagraphGroupElement);
+		}
+		
+		/** @private */	
+		private static function getNestedArgCount(obj:Object):uint
+		{
+			return (obj is Array) ? obj.length : 1;
+		}		
+		
+		/** @private */	
+		private static function getNestedArg(obj:Object, index:uint):FlowElement
+		{
+			CONFIG::debug { assert(index < getNestedArgCount(obj),"bad index to getNestedArg"); }; 
+			return ((obj is Array) ? obj[index] : obj) as FlowElement;
+		}
+				
+		/**
+		 * Replaces child elements in the group with the specified new elements. Use the <code>beginChildIndex</code> and
+		 * <code>endChildIndex</code> parameters to govern the operation as follows:
+		 * <p><ul>
+		 * <li>To delete elements, do not pass any replacement elements.</li>
+		 * <li>To insert elements, pass the same value for <code>beginChildIndex</code> and <code>endChildIndex</code>.  
+		 * The new elements is inserted before the specified index.</li>
+		 * <li>To append elements, pass <code>numChildren</code> for <code>beginChildIndex</code> and <code>endChildIndex</code>.</li>
+		 * </ul></p>
+		 * <p>Otherwise, this method replaces the specified elements, starting with the element at <code>beginChildIndex</code> 
+		 * and up to but not including <code>endChildIndex</code>.</p>
+		 * 
+		 * @param beginChildIndex The index value for the start position of the replacement range in the children array.
+		 * @param endChildIndex The index value following the end position of the replacement range in the children array.
+		 * @param rest The elements to replace the specified range of elements. Can be a sequence containing flow elements or
+		 * arrays or vectors thereof.
+		 *	 
+	     * @throws RangeError The <code>beginChildIndex</code> or <code>endChildIndex</code> specified is out of range.
+	     * 
+	     * @includeExample examples\FlowGroupElement_replaceChildrenExample.as -noswf
+		 *
+	     * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function replaceChildren(beginChildIndex:int, endChildIndex:int, ...rest):void
+		{
+			if (beginChildIndex > _numChildren || endChildIndex > _numChildren)
+				throw RangeError(GlobalSettings.resourceStringFunction("badReplaceChildrenIndex"));	
+			
+			var thisAbsStart:int = getAbsoluteStart();
+			var absStartIdx:int =  thisAbsStart + (beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart);
+			var relStartIdx:int = beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart;
+			
+			// deletion phase
+			if (beginChildIndex < endChildIndex)
+			{
+				var child:FlowElement;	// scratch variable
+				var len:int = 0;
+
+				while (beginChildIndex < endChildIndex)
+				{
+					child = this.getChildAt(beginChildIndex);
+					child.modelChanged(ModelChange.ELEMENT_REMOVAL, 0, child.textLength);
+					len += child.textLength;
+					
+					child.setParentAndRelativeStart(null,0);
+					if (_numChildren == 1)
+					{
+						_singleChild = null;
+						_numChildren = 0;
+					}
+					else
+					{
+						_childArray.splice(beginChildIndex,1);
+						_numChildren--;
+						if (_numChildren == 1)
+						{
+							_singleChild = _childArray[0];
+							_childArray = null;
+						}
+					}
+					endChildIndex--;
+				}
+				if (len)
+				{
+					// TODO: this code should move into updateLengths.  updateLengths needs a rewrite
+					// as it assumes that any element that is removed has its length set to zero and updateLengths
+					// is called on that element first.  replaceChildren doesn't do that - it just removes the element
+					
+					// until rewrite reuse endChildIndex and update start of all following elements
+					while (endChildIndex < _numChildren)
+					{
+						child = getChildAt(endChildIndex);
+						child.setParentRelativeStart(child.parentRelativeStart-len);
+						endChildIndex++;
+					}
+				
+					// update lengths
+					updateLengths(absStartIdx,-len,true);
+					
+					deleteContainerText(relStartIdx + len,len);
+				}
+			}
+			CONFIG::debug { assert(thisAbsStart == getAbsoluteStart(),"replaceChildren: Bad thisAbsStart"); }
+			var childrenToAdd:int = 0;		// number of children to add
+			var flatNewChildList:Array;		// stores number of children when > 1
+			var newChildToAdd:FlowElement;	// stores a single child to add - avoids creating an Array for the 99% case
+			 
+			var newChild:FlowElement; 		// scratch
+			var idx:int;					// scratch
+			
+			for each (var obj:Object in rest)
+			{
+				if (!obj)
+					continue;
+				
+				var numNestedArgs:int = getNestedArgCount(obj);
+				for (idx = 0; idx<numNestedArgs; idx++)
+				{
+					newChild = getNestedArg(obj, idx);
+					if (newChild)
+					{
+						if (newChild.parent)
+						{
+							if (newChild.parent == this)
+							{
+								// special handling in this case
+								var childIndex:int = getChildIndex(newChild);
+								newChild.parent.removeChild(newChild);
+								thisAbsStart = getAbsoluteStart();	// is it in the same flow?
+								if (childIndex <= beginChildIndex)
+								{
+									beginChildIndex--;
+									absStartIdx =  thisAbsStart + (beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart);
+									relStartIdx = beginChildIndex == _numChildren ? textLength : getChildAt(beginChildIndex).parentRelativeStart;
+								}
+							}
+							else
+							{
+								thisAbsStart = getAbsoluteStart();	// is it in the same flow?
+								newChild.parent.removeChild(newChild);
+							}
+						}
+						if (!canOwnFlowElement(newChild))
+							throw ArgumentError(GlobalSettings.resourceStringFunction("invalidChildType"));
+						
+						// manage as an array or a single child
+						if (childrenToAdd == 0)
+							newChildToAdd = newChild
+						else if (childrenToAdd == 1)
+							flatNewChildList = [ newChildToAdd, newChild ];
+						else
+							flatNewChildList.push(newChild);
+						childrenToAdd++;
+					}
+				}
+			}			
+
+			if (childrenToAdd)
+			{
+				// TODO-9/18/2008-ideally, do the following in one shot, but insertBlockElement
+				// called from setParentAndRelativeStart in the loop below has different behavior
+				// based on the size of _children (zero vs. non-zero)
+				//_children.splice(beginChildIndex,0,flatNewChildList);
+				var addedTextLength:uint = 0;
+				for (idx = 0; idx < childrenToAdd; idx++)
+				{
+					newChild = childrenToAdd == 1 ? newChildToAdd : flatNewChildList[idx];
+					
+					if (_numChildren == 0)
+						_singleChild = newChild;
+					else if (_numChildren > 1)
+						_childArray.splice(beginChildIndex,0,newChild);
+					else
+					{
+						_childArray = beginChildIndex == 0 ? [ newChild, _singleChild ] : [ _singleChild, newChild ];
+						_singleChild = null;
+					}
+					_numChildren++;
+					newChild.setParentAndRelativeStart(this,relStartIdx+addedTextLength);
+					addedTextLength += newChild.textLength;
+					beginChildIndex++;	// points to the next slot
+				}
+				CONFIG::debug { assert(thisAbsStart == getAbsoluteStart(),"replaceChildren: Bad thisAbsStart"); }
+				if (addedTextLength)
+				{
+					// update following elements - see comment above.
+					// it would be best if this loop only ran once
+					while (beginChildIndex < _numChildren)
+					{
+						child = getChildAt(beginChildIndex++);
+						child.setParentRelativeStart(child.parentRelativeStart+addedTextLength);
+					}
+					updateLengths(absStartIdx,addedTextLength,true);
+					var enclosingContainer:ContainerController = getEnclosingController(relStartIdx);
+					if (enclosingContainer)
+						ContainerController(enclosingContainer).setTextLength(enclosingContainer.textLength + addedTextLength);
+				}
+				for (idx = 0; idx < childrenToAdd; idx++)
+				{
+					newChild = childrenToAdd == 1 ? newChildToAdd : flatNewChildList[idx];
+					newChild.modelChanged(ModelChange.ELEMENT_ADDED, 0, newChild.textLength);
+				}
+			}
+			else 
+			{	
+				var tFlow:TextFlow = getTextFlow();
+				if (tFlow != null)
+				{
+					// beginChildIndex points to the next element
+					// use scratch idx as "damageStart"
+					if (beginChildIndex < _numChildren)
+            		{
+            			// first, look for the next element and damage the beginning.
+						idx = thisAbsStart + getChildAt(beginChildIndex).parentRelativeStart;
+            		} 
+            		else if (beginChildIndex > 1)
+            		{
+            			// damage the end of the previous element
+						newChild = getChildAt(beginChildIndex-1);
+						idx = thisAbsStart + newChild.parentRelativeStart + newChild.textLength - 1;
+            		} 
+					else
+					{
+						// damage the very end of the textFlow
+						idx = thisAbsStart;
+						if (idx >= tFlow.textLength)
+							idx--;
+     				}
+     				tFlow.damage(idx, 1, FlowDamageType.GEOMETRY, false);
+   				}   				
+			}
+		}
+		
+		/** 
+		 * Appends a child FlowElement object. The new child is added to the end of the children list.
+		 * 
+		 * @param child The child element to append.
+		 *
+		 * @return  the added child FlowElement 
+		 * 
+		 * @includeExample examples\FlowGroupElement_addChildExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function addChild(child:FlowElement):FlowElement
+		{
+			replaceChildren(_numChildren, _numChildren, child);
+			return child;
+		}
+		
+		/** 
+		 * Adds a child FlowElement object at the specified index position.
+		 *
+		 * @param The index of the position at which to add the child element, with the first position being 0.
+		 * @param child The child element to add.
+		 * @throws RangeError The <code>index</code> is out of range.
+		 *
+		 * @return  the added child FlowElement 
+		 *
+		 * @includeExample examples\FlowGroupElement_addChildAtExample.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		public function addChildAt(index:uint, child:FlowElement):FlowElement
+		{
+			replaceChildren(index, index, child);
+			return child;
+		}
+		
+		/** 
+		 * Removes the specified child FlowElement object from the group.
+		 *
+		 * @param child The child element to remove.
+		 * @throws ArgumentError The <code>child</code> is not found.
+		 *
+		 * @return  the removed child FlowElement object 
+		 *
+		 * @includeExample examples\FlowGroupElement_removeChildExample.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 *
+		 */
+		 
+		public function removeChild(child:FlowElement):FlowElement
+		{
+			var index:int = getChildIndex(child);
+			if (index == -1)
+				throw ArgumentError(GlobalSettings.resourceStringFunction("badRemoveChild"));
+				
+			removeChildAt(index);
+			return child;
+		}
+		
+		/** 
+		 * Removes the child FlowElement object at the specified index position.
+		 *
+		 * @param index position at which to remove the child element.
+		 * @throws RangeError The <code>index</code> is out of range.
+		 *
+		 * @return  the child FlowElement object removed from the specified position.
+		 *
+		 * @includeExample examples\FlowGroupElement_removeChildAtExample.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function removeChildAt(index:uint):FlowElement
+		{
+			var childToReplace:FlowElement = getChildAt(index);
+			replaceChildren(index, index+1);
+			return childToReplace;
+		}
+		
+		/** 
+		 * Splits this object at the position specified by the <code>childIndex</code> parameter. If this group element has 
+		 * a parent, creates a shallow copy of this object and replaces its children with the elements up to the index. Moves 
+		 * elements following <code>childIndex</code> into the copy.
+		 * 
+		 * @return the new FlowGroupElement object.
+		 * @throws RangeError if <code>childIndex</code> is greater than the length of the children.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function splitAtIndex(childIndex:int):FlowGroupElement
+		{
+			if (childIndex > _numChildren)
+				throw RangeError(GlobalSettings.resourceStringFunction("invalidSplitAtIndex"));
+					
+			var newSibling:FlowGroupElement = shallowCopy() as FlowGroupElement;
+
+			var numChildrenToMove:int = _numChildren-childIndex;
+			if (numChildrenToMove == 1)
+				newSibling.addChild(removeChildAt(childIndex));
+			else if (numChildrenToMove != 0)
+			{
+				var childArray:Array = _childArray.slice(childIndex);
+				this.replaceChildren(childIndex,_numChildren-1);
+				newSibling.replaceChildren(0, 0, childArray);		
+			}
+			
+			if (parent)
+			{
+				var myidx:int = parent.getChildIndex(this);
+				parent.replaceChildren(myidx+1,myidx+1,newSibling);
+			}
+
+			return newSibling;
+		}
+
+		/** 
+		 * Splits this object at the position specified by the <code>relativePosition</code> parameter, where 
+		 * the relative position is a relative text position in this element.
+		 * 
+		 * @throws RangeError if relativePosition is greater than textLength, or less than 0.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @private
+		 */
+		 
+		public override function splitAtPosition(relativePosition:int):FlowElement
+		{
+			// Creates a shallowCopy of this and adds it to parent after this.  
+			// Moves elements from characterIndex forward into the copy
+		 	// returns the new shallowCopy
+			if ((relativePosition < 0) || (relativePosition > textLength))
+				throw RangeError(GlobalSettings.resourceStringFunction("invalidSplitAtPosition"));
+			
+			var curElementIdx:int;
+			
+			if (relativePosition == textLength)
+				curElementIdx = _numChildren;
+			else
+			{
+				curElementIdx = findChildIndexAtPosition(relativePosition);
+				var curFlowElement:FlowElement = getChildAt(curElementIdx);
+				
+				if (curFlowElement.parentRelativeStart != relativePosition)
+				{										
+					if (curFlowElement is FlowGroupElement)
+					{
+						FlowGroupElement(curFlowElement).splitAtPosition(relativePosition - curFlowElement.parentRelativeStart);
+					} 
+					else
+					{
+						//I would imagine that it has to be a span.  That's the only non-FlowGroupElement
+						//type that can take up more than a textLength of 1.
+						CONFIG::debug { assert(curFlowElement is SpanElement, "SpanElements are the only leaf elements that can currently have > 1 textLength");	}			
+						SpanElement(curFlowElement).splitAtPosition(relativePosition - curFlowElement.parentRelativeStart);
+					}
+					//increase by one. It's the new element that we want to move over.
+					curElementIdx++;
+				}
+			}
+			
+			//increase by one. It's the new element that we want to move over.
+			return splitAtIndex(curElementIdx);
+		} 		 
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			var idx:int = findChildIndexAtPosition(normalizeStart);
+			if (idx != -1 && idx < _numChildren)
+			{
+				// backup over zero length children
+				var child:FlowElement = getChildAt(idx);
+				normalizeStart = normalizeStart-child.parentRelativeStart;
+				
+				CONFIG::debug { assert(normalizeStart >= 0, "bad normalizeStart in normalizeRange"); }
+				for (;;)
+				{
+					// watch out for changes in the length of the child
+					var origChildEnd:int = child.parentRelativeStart+child.textLength;
+					child.normalizeRange(normalizeStart,normalizeEnd-child.parentRelativeStart);
+					var newChildEnd:int = child.parentRelativeStart+child.textLength;
+					normalizeEnd += newChildEnd-origChildEnd;	// adjust
+					
+					// no zero length children
+					if (child.textLength == 0 && !child.bindableElement)
+						replaceChildren(idx,idx+1);
+					else
+						idx++;
+
+					if (idx == _numChildren)
+						break;
+					
+					// next child
+					child = getChildAt(idx);
+					
+					if (child.parentRelativeStart > normalizeEnd)
+						break;
+						
+					normalizeStart = 0;		// for the next child	
+				}
+			}
+
+
+		}
+		
+		/** @private */
+		tlf_internal override function applyWhiteSpaceCollapse():void
+		{
+			for (var idx:int = 0; idx < _numChildren;)
+			{
+				var child:FlowElement = getChildAt(idx);
+				child.applyWhiteSpaceCollapse();
+				if (child.parent == this)	// check to see if child was removed (could have been 
+					++idx;
+			}
+				
+			// If the element was added automatically, it may now have no content and needs to be removed
+			// This can happen with whitespace between paragraphs that is added by set mxmlChildren
+			if (textLength == 0  && impliedElement && parent != null)
+				parent.removeChild(this);
+
+			super.applyWhiteSpaceCollapse();
+		}
+		
+		/** @private */
+		tlf_internal override function appendElementsForDelayedUpdate(tf:TextFlow):void
+		{ 
+			for (var idx:int = 0; idx < _numChildren; idx++)
+			{
+				var child:FlowElement = getChildAt(idx);
+				child.appendElementsForDelayedUpdate(tf);
+			}
+		}
+		
+
+		
+			
+		// **************************************** 
+		// End tree modification support code
+		// ****************************************	
+		// **************************************** 
+		// Begin debug support code
+		// ****************************************	
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			
+			var rslt:int = super.debugCheckFlowElement(depth,extraData);
+			
+			// debugging function that asserts if the flow element is in an invalid state
+			var totalChildLength:int = 0;
+			if (_numChildren)
+			{
+				for (var childIndex:int = 0; childIndex < _numChildren; ++childIndex)
+				{
+					var child:FlowElement = getChildAt(childIndex);
+					rslt += assert(child.parent == this, "child doesn't point to parent");
+
+					// totalChildLength is relative offset to child
+					rslt += assert(child.parentRelativeStart == totalChildLength, "child start offset wrong");
+					rslt += child.debugCheckFlowElement(depth+1);
+					totalChildLength += child.textLength;				
+				}
+			}
+			else	
+			{
+				// only spans may own text
+				rslt += assert(this is SpanElement || textLength == 0, "only spans may have text");	
+				totalChildLength = textLength;	
+			}
+			assert(totalChildLength == textLength, "child total textLength wrong");
+			return rslt;
+		}		
+		// **************************************** 
+		// End debug support code
+		// ****************************************	
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/FlowLeafElement.as b/textLayout_core/src/flashx/textLayout/elements/FlowLeafElement.as
new file mode 100755
index 0000000..a16e118
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/FlowLeafElement.as
@@ -0,0 +1,992 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.Shape;
+	import flash.events.EventDispatcher;
+	import flash.geom.Rectangle;
+	import flash.text.engine.ContentElement;
+	import flash.text.engine.ElementFormat;
+	import flash.text.engine.FontDescription;
+	import flash.text.engine.FontMetrics;
+	import flash.text.engine.TextBaseline;
+	import flash.text.engine.TextElement;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextRotation;
+	import flash.text.engine.TypographicCase;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.compose.FlowComposerBase;
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BackgroundColor;
+	import flashx.textLayout.formats.BaselineShift;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.IMEStatus;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TLFTypographicCase;
+	import flashx.textLayout.formats.TextDecoration;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.CharacterUtil;
+	import flashx.textLayout.utils.LocaleUtil;
+	
+	use namespace tlf_internal;
+		
+	
+	/** Base class for FlowElements that appear at the lowest level of the flow hierarchy. FlowLeafElement objects have
+	* no children and include InlineGraphicElement objects and SpanElement objects.
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*
+	* @see InlineGraphicElement
+	* @see SpanElement
+	*/
+	public class FlowLeafElement extends FlowElement
+	{				
+		/** Holds the content of the leaf @private */
+		protected var _blockElement:ContentElement;
+		
+		/** @private
+		 * Holds the text for the leaf element - unless there's a valid blockElement, 
+		 * in which case the text is in the rawText field of the blockElement.
+		 */
+		protected var _text:String;	// holds the text property if the blockElement is null
+		private var _hasAttachedListeners:Boolean;	// true if FTE eventMirror may be in use
+		
+		/** 
+		 * Base class - invoking new FlowLeafElement() throws an error exception. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 */
+		public function FlowLeafElement()
+		{
+			_hasAttachedListeners = false;
+			super();
+		}
+		
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			CONFIG::debug { assert(_blockElement != null, "_blockElement not allocated in derived class"); }
+			if (_computedFormat)
+			{
+				_blockElement.elementFormat = getCanonicalElementFormat();
+				CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementFormat",_blockElement.elementFormat); }
+			}
+			if (parent)
+				parent.insertBlockElement(this,_blockElement);
+		}
+		/** @private */
+		override tlf_internal function releaseContentElement():void
+		{
+			if (!canReleaseContentElement() || _blockElement == null)
+				return;
+				
+			_blockElement = null;
+		}
+		/** @private */
+		override tlf_internal function canReleaseContentElement():Boolean
+		{
+			return !_hasAttachedListeners;
+		}
+		
+		private function blockElementExists():Boolean
+		{
+			return _blockElement != null;
+		}
+
+		/** @private */
+		tlf_internal function getBlockElement():ContentElement
+		{ 
+			if (!_blockElement)
+				createContentElement();
+			return _blockElement; 
+		}
+		
+		
+		/**
+		 * The text associated with the FlowLeafElement:
+		 * <p><ul>
+		 * <li>The value for SpanElement subclass will be one character less than <code>textLength</code> if this is the last span in a ParagraphELement.</li>
+		 * <li>The value for BreakElement subclass is a U+2028</li>
+		 * <li>The value for TabElement subclass is a tab</li>
+		 * <li>The value for InlineGraphicElement subclass is U+FDEF</li>
+		 * </ul></p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.elements.SpanElement#replaceText()
+		 */
+		public function get text():String
+		{
+			return _blockElement ?  _blockElement.rawText : _text;
+		}
+		
+		/** @private */
+		tlf_internal function getElementFormat():ElementFormat
+		{ 			
+			if (!_blockElement)
+				createContentElement();
+			return _blockElement.elementFormat; 
+ 		}
+		
+		/** @private */
+		tlf_internal override function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
+		{
+			if (newParent == parent)
+				return;
+		
+			var hasBlock:Boolean = _blockElement != null;
+			
+			if (_blockElement && parent && parent.hasBlockElement())	// remove textElement from the parent content
+				parent.removeBlockElement(this,_blockElement);
+			if (newParent && !newParent.hasBlockElement() && _blockElement)
+				newParent.createContentElement();
+					
+			super.setParentAndRelativeStart(newParent,newStart);
+			
+			// Update the FTE ContentElement structure. If the parent has FTE elements, then create FTE elements for the leaf node 
+			// if it doesn't already have them, and add them in. If the parent does not have FTE elements, release the leaf's FTE
+			// elements also so they match.
+			if (parent)
+			{
+				if (parent.hasBlockElement())
+				{
+					if (!_blockElement)
+						createContentElement();
+					else if (hasBlock)	// don't do this if the _blockElement was constructed as side-effect of setParentAndRelativeStart; in that case, it's already attached
+						parent.insertBlockElement(this,_blockElement);
+				}
+				else if (_blockElement)
+					releaseContentElement();
+			}
+		}
+	
+		/** @private */
+		protected function quickInitializeForSplit(sibling:FlowLeafElement,newSpanLength:int,newSpanTextElement:TextElement):void
+		{
+			setTextLength(newSpanLength);
+			_blockElement = newSpanTextElement;
+			quickCloneTextLayoutFormat(sibling);
+			var tf:TextFlow = sibling.getTextFlow();
+			if (tf == null || tf.formatResolver == null)
+			{
+				_computedFormat = sibling._computedFormat;
+				if (_blockElement)
+					_blockElement.elementFormat = sibling.getElementFormat();
+			}
+		}
+		
+		/** @private */
+		tlf_internal function addParaTerminator():void
+		{
+			// some FlowLeafElement types have RO text and can't have a paragraph terminator
+			CONFIG::debug { assert(false,"TODO: para terminator in non-span leaves"); }
+		}
+		/** @private */
+		tlf_internal function removeParaTerminator():void
+		{
+			// some FlowLeafElement types have RO text and can't have a paragraph terminator
+			CONFIG::debug { assert(false,"TODO: para terminator in non-span leaves"); }
+		}
+		
+		/**
+		 * Returns the next FlowLeafElement object.  
+		 * 
+		 * @param limitElement	Specifies FlowGroupElement on whose last leaf to stop looking. A value of null (default) 
+		 * 	means search till no more elements.
+		 * @return 	next FlowLeafElement or null if at the end
+		 *
+		 * @includeExample examples\FlowLeafElement_getNextLeafExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		 public function getNextLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
+		{
+			if (!parent)
+				return null;
+			return parent.getNextLeafHelper(limitElement,this);
+		}
+		
+		/**
+		 * Returns the previous FlowLeafElement object.  
+		 * 
+		 * @param limitElement	Specifies the FlowGroupElement on whose first leaf to stop looking.   null (default) means search till no more elements.
+		 * @return 	previous leafElement or null if at the end
+		 *
+		 * @includeExample examples\FlowLeafElement_getPreviousLeafExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 */
+		 
+		public function getPreviousLeaf(limitElement:FlowGroupElement=null):FlowLeafElement
+		{
+			if (!parent)
+				return null;
+			return parent.getPreviousLeafHelper(limitElement,this);
+		}
+		
+		/** @private */
+		public override function getCharAtPosition(relativePosition:int):String
+		{
+			var textValue:String = _blockElement ? _blockElement.rawText : _text;
+			if (textValue)
+				return textValue.charAt(relativePosition);
+			return String("");
+		} 
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			// this does the cascade - potential optimization to skip it if the _blockElement isn't attached
+			computedFormat;
+		}
+		
+		/** Returns the FontMetrics object for the span. The properties of the FontMetrics object describe the 
+		 * emBox, strikethrough position, strikethrough thickness, underline position, 
+		 * and underline thickness for the specified font. 
+		 *
+ 		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flash.text.engine.FontMetrics
+		 * @see flash.text.engine.ElementFormat#getFontMetrics()
+		 *
+		 * @return font metrics associated with the span
+		 */
+		public function getComputedFontMetrics():FontMetrics
+		{
+			if (!_blockElement)
+				createContentElement();
+			var ef:ElementFormat = _blockElement.elementFormat;
+			if (!ef)
+				return null;
+				
+			var tf:TextFlow = getTextFlow()
+			if (tf && tf.flowComposer && tf.flowComposer.swfContext)
+				return tf.flowComposer.swfContext.callInContext(ef.getFontMetrics,ef,null,true);
+
+			return ef.getFontMetrics();
+		}
+	
+		static private var _elementFormats:Dictionary = new Dictionary(true);
+		
+		/** @private 
+		 */
+		tlf_internal static function clearElementFormatsCache():void
+		{ 
+			for each (var elementFormat:ElementFormat in _elementFormats)
+			{
+				// At least one entry exists. Create a new dictionary and return.
+				// This may be cheaper than deleting all entries one by one.
+				_elementFormats = new Dictionary(true);
+				return;
+			}
+		}
+		
+		/** @private */
+		private function resolveDomBaseline():String
+		{
+			CONFIG::debug { assert(_computedFormat != null,"bad call to resolveDomBaseline"); }
+			
+			var domBase:String = _computedFormat.dominantBaseline;
+			if(domBase == FormatValue.AUTO)
+			{
+				if(this.computedFormat.textRotation == TextRotation.ROTATE_270 /*|| 
+					this.computedFormat.blockProgression == BlockProgression.RL*/)
+					domBase = TextBaseline.IDEOGRAPHIC_CENTER;
+				else
+				{
+					var para:ParagraphElement = getParagraph();
+					//otherwise, avoid using the locale of the element and use the paragraph's locale
+					if(para != null)
+						domBase = para.getEffectiveDominantBaseline();
+					else
+						domBase = LocaleUtil.dominantBaseline(_computedFormat.locale);
+				}
+			}
+			
+			return domBase;
+		}
+		
+		/** @private */
+		private function getCanonicalElementFormat():ElementFormat
+		{
+			CONFIG::debug { assert(_computedFormat != null,"bad call to getCanonicalElementFormat"); }
+			
+			var domBase:String = resolveDomBaseline();
+			
+			// the fontLookup may be override by the resolveFontLookupFunction
+			var fontLookup:String;
+			if (GlobalSettings.resolveFontLookupFunction == null)
+				fontLookup = _computedFormat.fontLookup
+			else
+			{
+				var flowComposer:IFlowComposer = getTextFlow().flowComposer;
+				fontLookup = GlobalSettings.resolveFontLookupFunction(flowComposer ? FlowComposerBase.computeBaseSWFContext(flowComposer.swfContext) : null,_computedFormat);
+			}
+			
+			var format:ElementFormat = _elementFormats[_computedFormat] as ElementFormat;
+			if (!format || format.dominantBaseline != domBase || format.fontDescription.fontLookup != fontLookup)
+			{
+				// compute the cascaded elementFormat
+				format = new ElementFormat();
+				CONFIG::debug { Debugging.traceFTECall(format,null,"new ElementFormat()"); }
+				
+				format.alignmentBaseline	= _computedFormat.alignmentBaseline;
+				format.alpha				= Number(_computedFormat.textAlpha);
+				format.breakOpportunity		= _computedFormat.breakOpportunity;
+				format.color				= uint(_computedFormat.color);
+				format.dominantBaseline		= domBase;
+				
+				format.digitCase			= _computedFormat.digitCase;
+				format.digitWidth			= _computedFormat.digitWidth;
+				format.ligatureLevel		= _computedFormat.ligatureLevel;
+				format.fontSize				= Number(_computedFormat.fontSize);
+				format.kerning				= _computedFormat.kerning;
+				format.locale				= _computedFormat.locale;
+				format.trackingLeft			= TextLayoutFormat.trackingLeftProperty.computeActualPropertyValue(_computedFormat.trackingLeft,format.fontSize);
+				format.trackingRight		= TextLayoutFormat.trackingRightProperty.computeActualPropertyValue(_computedFormat.trackingRight,format.fontSize);
+				format.textRotation			= _computedFormat.textRotation;
+				format.baselineShift 		= -(TextLayoutFormat.baselineShiftProperty.computeActualPropertyValue(_computedFormat.baselineShift, format.fontSize));
+				switch (_computedFormat.typographicCase)
+				{
+					case TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS:
+						format.typographicCase = TypographicCase.CAPS_AND_SMALL_CAPS;
+						break;
+					case TLFTypographicCase.CAPS_TO_SMALL_CAPS:
+						format.typographicCase = TypographicCase.SMALL_CAPS;
+						break;
+					/* These map directly so we handle it in the default case
+					case TLFTypographicCase.LOWERCASE:
+						format.typographicCase = TypographicCase.LOWERCASE;
+						break;
+					case TLFTypographicCase.DEFAULT:
+						format.typographicCase = TypographicCase.DEFAULT;
+						break;
+					case TLFTypographicCase.UPPERCASE:
+						format.typographicCase = TypographicCase.UPPERCASE;
+						break;
+					*/
+					default:
+						format.typographicCase = _computedFormat.typographicCase;
+						break;
+				}
+				
+				CONFIG::debug { Debugging.traceFTEAssign(format,"alignmentBaseline",format.alignmentBaseline); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"alpha",format.alpha); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"breakOpportunity",format.breakOpportunity); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"color",format.color); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"dominantBaseline",format.dominantBaseline); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"digitCase",format.digitCase); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"digitWidth",format.digitWidth); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"ligatureLevel",format.ligatureLevel); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"fontSize",format.fontSize); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"kerning",format.kerning); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"locale",format.locale); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"trackingLeft",format.trackingLeft); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"trackingRight",format.trackingRight); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"typographicCase",format.typographicCase); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"textRotation",format.textRotation); }
+				CONFIG::debug { Debugging.traceFTEAssign(format,"baselineShift",format.baselineShift);	 }	
+								
+				// set the fontDesription in the cascadedFormat
+				var fd:FontDescription = new FontDescription();
+				fd.fontWeight = _computedFormat.fontWeight;
+				fd.fontPosture = _computedFormat.fontStyle;
+				fd.fontName = _computedFormat.fontFamily;
+				fd.renderingMode = _computedFormat.renderingMode;
+				fd.cffHinting = _computedFormat.cffHinting;
+				fd.fontLookup = fontLookup;
+				var fontMapper:Function = GlobalSettings.fontMapperFunction;
+				if (fontMapper != null)
+					fontMapper(fd);
+				CONFIG::debug { Debugging.traceFTECall(fd,null,"new FontDescription()"); }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"fontWeight",fd.fontWeight);	 }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"fontPosture",fd.fontPosture);	 }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"fontName",fd.fontName);	 }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"renderingMode",fd.renderingMode);	 }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"cffHinting",fd.cffHinting);	 }
+				CONFIG::debug { Debugging.traceFTEAssign(fd,"fontLookup",fd.fontLookup);	 }
+				
+				format.fontDescription = fd;
+				CONFIG::debug { Debugging.traceFTEAssign(format,"fontDescription",fd); }
+				
+				//Moved code here because original code tried to access fontMetrics prior to setting the elementFormat.
+				//Since getFontMetrics returns the value of blockElement.elementFormat.getFontMetrics(), we cannot call this
+				//until after the element has been set. Watson 1820571 - gak 06.11.08
+				// Adjust format for superscript/subscript
+				if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT || 
+					_computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
+				{
+					var fontMetrics:FontMetrics;
+					var tf:TextFlow = getTextFlow();
+					if (tf.flowComposer && tf.flowComposer.swfContext)
+						fontMetrics = tf.flowComposer.swfContext.callInContext(format.getFontMetrics,format,null,true);
+					else	
+						fontMetrics = format.getFontMetrics();	
+					if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
+					{
+						format.baselineShift = (fontMetrics.superscriptOffset * format.fontSize);
+						format.fontSize = fontMetrics.superscriptScale * format.fontSize;
+					}
+					else // it's subscript
+					{
+						format.baselineShift = (fontMetrics.subscriptOffset * format.fontSize);
+						format.fontSize = fontMetrics.subscriptScale * format.fontSize;
+					}
+					CONFIG::debug { Debugging.traceFTEAssign(format,"baselineShift",format.baselineShift); }
+					CONFIG::debug { Debugging.traceFTEAssign(format,"fontSize",format.fontSize); }
+				}
+				
+				_elementFormats[_computedFormat] = format;
+			}
+			
+			return format;
+		}
+
+		/** 
+		 * The computed text format attributes that are in effect for this element.
+		 * Takes into account the inheritance of attributes.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flashx.textLayout.formats.ITextLayoutFormat
+		 */
+		public override function get computedFormat():ITextLayoutFormat
+		{		
+			if (!_computedFormat)
+			{
+				doComputeTextLayoutFormat(formatForCascade);
+
+				if (_blockElement)
+				{
+					_blockElement.elementFormat = getCanonicalElementFormat();
+					CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementFormat",_blockElement.elementFormat); }
+				}
+
+			}
+			return _computedFormat;
+		}
+		
+		/** Returns the fontSize from this element's properties.  @private */
+		tlf_internal function getEffectiveFontSize():Number
+		{
+			return Number(computedFormat.fontSize);
+		}
+		/** @private */
+		tlf_internal function getSpanBoundsOnLine(textLine:TextLine, blockProgression:String):Array
+		{
+			var line:TextFlowLine = TextFlowLine(textLine.userData);
+			var paraStart:int = line.paragraph.getAbsoluteStart();
+			var lineEnd:int = (line.absoluteStart + line.textLength) - paraStart;
+			var spanStart:int = getAbsoluteStart() - paraStart;		// get start pos relative to the paragraph (which might not be the parent)
+			var endPos:int = spanStart + text.length;		// so we don't include the paragraph terminator character, if present
+		
+			// Clip to start of line	
+			var startPos:int = Math.max(spanStart, line.absoluteStart - paraStart);
+			
+			// Clip to end of line	
+			// Heuristic for detecting spaces at the end of the line and eliminating them from the range so they won't be underlined.
+			if (endPos >= lineEnd)
+			{
+				endPos = lineEnd;
+				var spanText:String = text;
+				while (endPos > startPos && CharacterUtil.isWhitespace(spanText.charCodeAt(endPos - spanStart - 1)))
+					--endPos;
+			}
+
+			var mainRects:Array = [];
+			line.calculateSelectionBounds(textLine, mainRects, startPos, endPos, blockProgression, [ line.textHeight,0]);
+			return mainRects;
+		}
+		
+		/** @private */
+		tlf_internal function updateIMEAdornments(line:TextFlowLine, blockProgression:String, imeStatus:String):void
+		{
+			var tLine:TextLine = line.getTextLine();
+			var metrics:FontMetrics = getComputedFontMetrics();
+			var spanBoundsArray:Array = getSpanBoundsOnLine(tLine, blockProgression);
+			//this is pretty much always going to have a length of 1, but just to be sure...
+			for (var i:int = 0; i < spanBoundsArray.length; i++)
+			{
+				//setup ime variables
+				var imeLineThickness:int = 1;
+				var imeLineColor:uint = 0x000000;
+				var imeLineStartX:Number = 0;
+				var imeLineStartY:Number = 0;
+				var imeLineEndX:Number = 0;
+				var imeLineEndY:Number = 0;
+				
+				//selected text draws with 2 px
+				if(imeStatus == IMEStatus.SELECTED_CONVERTED || imeStatus == IMEStatus.SELECTED_RAW)
+				{
+					imeLineThickness = 2;
+				}
+				//Raw or deadkey text draws with grey
+				if(imeStatus == IMEStatus.SELECTED_RAW || imeStatus == IMEStatus.NOT_SELECTED_RAW
+					|| imeStatus == IMEStatus.DEAD_KEY_INPUT_STATE)
+				{
+					imeLineColor = 0xA6A6A6;
+				}
+				
+				var spanBounds:Rectangle = spanBoundsArray[i] as Rectangle;
+				var stOffset:Number = calculateStrikeThrough(tLine, blockProgression, metrics);
+				var ulOffset:Number = calculateUnderlineOffset(stOffset, blockProgression, metrics, tLine);
+				
+				if (blockProgression != BlockProgression.RL)
+				{
+					imeLineStartX = spanBounds.topLeft.x + 1;
+					imeLineEndX = spanBounds.topLeft.x + spanBounds.width - 1;
+					imeLineStartY = ulOffset;
+					imeLineEndY = ulOffset;
+				}
+				else
+				{
+					//is this TCY?
+					var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
+					imeLineStartY = spanBounds.topLeft.y + 1;
+					imeLineEndY = spanBounds.topLeft.y + spanBounds.height - 1;
+					
+					//elemIdx can sometimes be negative if the text is being wrapped due to a
+					//resize gesture - in which case the tLine has not necessarily been updated.
+					//If the elemIdx is invalid, just treat it like it's normal ttb text - gak 07.08.08
+					if(elemIdx < 0 || tLine.atomCount <= elemIdx || tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
+					{
+						imeLineStartX = ulOffset;
+						imeLineEndX = ulOffset;
+					}
+					else
+					{
+						//it is TCY!
+						var tcyParent:TCYElement =  this.getParentByType(TCYElement) as TCYElement;
+						CONFIG::debug{ assert(tcyParent != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
+						
+						//only perform calculations for TCY adornments when we are on the last leaf.  ONLY the last leaf matters
+						if((this.getAbsoluteStart() + this.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
+						{
+							var tcyAdornBounds:Rectangle = new Rectangle();
+							tcyParent.calculateAdornmentBounds(tcyParent, tLine, blockProgression, tcyAdornBounds);
+							var baseULAdjustment:Number = metrics.underlineOffset + (metrics.underlineThickness/2);
+							
+							imeLineStartY = tcyAdornBounds.top + 1;
+							imeLineEndY = tcyAdornBounds.bottom - 1;
+							imeLineStartX = spanBounds.bottomRight.x + baseULAdjustment;
+							imeLineEndX = spanBounds.bottomRight.x + baseULAdjustment;
+						}
+					}
+				}
+				
+				//Build the shape
+				var selObj:Shape = new Shape();
+				//TODO - this is probably going to need to be overridable in the full implementation
+				selObj.alpha = 1;       				
+				selObj.graphics.beginFill(imeLineColor);
+				
+				selObj.graphics.lineStyle(imeLineThickness, imeLineColor, selObj.alpha);
+				selObj.graphics.moveTo(imeLineStartX, imeLineStartY);
+				selObj.graphics.lineTo(imeLineEndX, imeLineEndY);
+				
+				selObj.graphics.endFill();
+				tLine.addChild(selObj);
+			}
+		}
+		
+		
+		/** @private return number of shapes added */
+		tlf_internal function updateAdornments(line:TextFlowLine, blockProgression:String):int
+		{
+			CONFIG::debug { assert(_computedFormat != null,"invalid call to updateAdornments"); }
+
+			// Only work on lines with strikethrough or underline
+			if (_computedFormat.textDecoration == TextDecoration.UNDERLINE || _computedFormat.lineThrough || _computedFormat.backgroundAlpha > 0 && _computedFormat.backgroundColor != BackgroundColor.TRANSPARENT)
+			{
+				var tLine:TextLine = line.getTextLine(true);
+				var spanBoundsArray:Array = getSpanBoundsOnLine(tLine, blockProgression);
+				for (var i:int = 0; i < spanBoundsArray.length; i++)
+					updateAdornmentsOnBounds(line, tLine, blockProgression, spanBoundsArray[i]);
+				return spanBoundsArray.length ;
+			}
+			return 0;
+		}
+		 
+		private function updateAdornmentsOnBounds(line:TextFlowLine, tLine:TextLine, blockProgression:String, spanBounds:Rectangle):void
+		{
+			CONFIG::debug { assert(_computedFormat != null,"invalid call to updateAdornmentsOnBounds"); }
+
+   			var selObj:Shape = new Shape();
+			var metrics:FontMetrics = getComputedFontMetrics();
+		
+			selObj.alpha = Number(_computedFormat.textAlpha);       				
+						
+			selObj.graphics.beginFill(uint(_computedFormat.color));
+			var stOffset:Number = calculateStrikeThrough(tLine, blockProgression, metrics);
+			var ulOffset:Number = calculateUnderlineOffset(stOffset, blockProgression, metrics, tLine);
+						
+			if (blockProgression != BlockProgression.RL)
+			{
+				if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
+				{
+					selObj.graphics.lineStyle(metrics.underlineThickness, _computedFormat.color as uint, selObj.alpha);
+					selObj.graphics.moveTo(spanBounds.topLeft.x, ulOffset);
+					selObj.graphics.lineTo(spanBounds.topLeft.x + spanBounds.width, ulOffset);
+				}
+				
+				if((_computedFormat.lineThrough))
+				{
+					selObj.graphics.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint, selObj.alpha);
+					selObj.graphics.moveTo(spanBounds.topLeft.x, stOffset);
+					selObj.graphics.lineTo(spanBounds.topLeft.x + spanBounds.width, stOffset);
+				}
+				
+				addBackgroundRect (line, tLine, metrics, spanBounds, true); 
+			}
+			else
+			{
+				//is this TCY?
+				var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
+				
+				//elemIdx can sometimes be negative if the text is being wrapped due to a
+				//resize gesture - in which case the tLine has not necessarily been updated.
+				//If the elemIdx is invalid, just treat it like it's normal ttb text - gak 07.08.08
+				if(elemIdx < 0 || tLine.atomCount <= elemIdx || tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
+				{
+					if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
+					{
+						selObj.graphics.lineStyle(metrics.underlineThickness, _computedFormat.color as uint, selObj.alpha);
+						selObj.graphics.moveTo(ulOffset, spanBounds.topLeft.y);
+						selObj.graphics.lineTo(ulOffset, spanBounds.topLeft.y + spanBounds.height);
+					}
+					
+					if (_computedFormat.lineThrough == true)
+					{
+						selObj.graphics.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint, selObj.alpha);
+						selObj.graphics.moveTo(-stOffset, spanBounds.topLeft.y);
+						selObj.graphics.lineTo(-stOffset, spanBounds.topLeft.y + spanBounds.height);															
+					}
+					
+					addBackgroundRect (line, tLine, metrics, spanBounds, false);
+				}
+				else
+				{
+					//it is TCY!
+					var tcyParent:TCYElement =  this.getParentByType(TCYElement) as TCYElement;
+					CONFIG::debug{ assert(tcyParent != null, "What kind of object is this that is ROTATE_0, but not TCY?");}
+					
+					//if the locale of the paragraph is Chinese, we need to adorn along the left and not right side.
+					var tcyPara:ParagraphElement = this.getParentByType(ParagraphElement) as ParagraphElement;
+					var lowerLocale:String = tcyPara.computedFormat.locale.toLowerCase();
+					var adornRight:Boolean = (lowerLocale.indexOf("zh") != 0);
+					
+					addBackgroundRect (line, tLine, metrics, spanBounds, true, true); 
+					
+					//only perform calculations for TCY adornments when we are on the last leaf.  ONLY the last leaf matters
+					if((this.getAbsoluteStart() + this.textLength) == (tcyParent.getAbsoluteStart() + tcyParent.textLength))
+					{
+						var tcyAdornBounds:Rectangle = new Rectangle();
+						tcyParent.calculateAdornmentBounds(tcyParent, tLine, blockProgression, tcyAdornBounds);
+						
+						if (_computedFormat.textDecoration == TextDecoration.UNDERLINE)
+						{
+							selObj.graphics.lineStyle(metrics.underlineThickness, _computedFormat.color as uint, selObj.alpha);
+							var baseULAdjustment:Number = metrics.underlineOffset + (metrics.underlineThickness/2);
+							var xCoor:Number = adornRight ? spanBounds.right : spanBounds.left;
+							if(!adornRight)
+								baseULAdjustment = -baseULAdjustment;
+							
+							selObj.graphics.moveTo(xCoor + baseULAdjustment, tcyAdornBounds.top);
+							selObj.graphics.lineTo(xCoor + baseULAdjustment, tcyAdornBounds.bottom);
+						}
+
+						if (_computedFormat.lineThrough == true)
+						{
+							var tcyMid:Number = spanBounds.bottomRight.x - tcyAdornBounds.x;
+							tcyMid /= 2;
+							tcyMid += tcyAdornBounds.x;
+							
+							selObj.graphics.lineStyle(metrics.strikethroughThickness, _computedFormat.color as uint, selObj.alpha);
+							selObj.graphics.moveTo(tcyMid, tcyAdornBounds.top);
+							selObj.graphics.lineTo(tcyMid, tcyAdornBounds.bottom);
+						}
+						
+					}
+				}
+			}
+			
+			selObj.graphics.endFill();
+			tLine.addChild(selObj);
+		}
+		
+		/** @private
+		 * Adds the background rectangle (if needed), making adjustments for glyph shifting as appropriate
+		 */
+		 private function addBackgroundRect(line:TextFlowLine, tLine:TextLine, metrics:FontMetrics, spanBounds:Rectangle, horizontalText:Boolean, isTCY:Boolean=false):void
+		 {
+			if(_computedFormat.backgroundAlpha == 0 || _computedFormat.backgroundColor == BackgroundColor.TRANSPARENT)
+				return;
+				
+			var tf:TextFlow = this.getTextFlow();
+			// ensure the TextFlow has a background manager - but its only supported with the StandardFlowComposer at this time
+			if(!tf.backgroundManager && (tf.flowComposer is StandardFlowComposer))
+				tf.backgroundManager = StandardFlowComposer(tf.flowComposer).createBackgroundManager();
+			
+			if (!tf.backgroundManager)
+				return;
+					
+			// The background rectangle usually needs to coincide with the passsed-in span bounds.
+			var r:Rectangle = spanBounds.clone();
+			
+			// With constrained glyph shifting (such as when superscript/subscript are in use), we'd like the
+			// background rectangle to follow the glyphs. Not so for arbitrary glyph shifting (such as when 
+			// baseline shift or baseline alignment are in use)	 	
+			// TODO-06/12/2009: Need to figure out adjustment for TCY background rect. No adjustment for now.
+			if (!isTCY && (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT || _computedFormat.baselineShift == BaselineShift.SUBSCRIPT))
+			{	
+				// The atom bounds returned by FTE do not reflect the effect of glyph shifting.
+				// We approximate this effect by making the following assumptions (strikethrough/underline code does the same)
+				// - The strike-through adornment runs through the center of the glyph
+				// - The Roman baseline is halfway between the center and bottom (descent)
+				// Effectively, the glyph's descent equals the strike-through offset, and its ascent is three times that
+				
+				var desiredExtent:Number; // The desired extent of the rectangle in the block progression direction
+				var baselineShift:Number; 
+				var fontSize:Number = getEffectiveFontSize();
+				var baseStrikethroughOffset:Number = metrics.strikethroughOffset + metrics.strikethroughThickness/2;
+				
+				if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
+				{
+					// The rectangle needs to sit on the line's descent and must extend far enough to accommodate the
+					// ascender of the glyph (that has moved up because of superscript)
+					
+					var glyphAscent:Number = -3 * baseStrikethroughOffset; // see assumptions above
+					baselineShift = -metrics.superscriptOffset * fontSize;
+					var lineDescent:Number = tLine.getBaselinePosition(TextBaseline.DESCENT) - tLine.getBaselinePosition(TextBaseline.ROMAN);
+					
+					desiredExtent = glyphAscent  + baselineShift + lineDescent;
+					if (horizontalText)
+					{
+						if (desiredExtent > r.height)
+						{
+							r.y -= desiredExtent - r.height;
+							r.height = desiredExtent;
+						}
+					}
+					else
+					{
+						if (desiredExtent > r.width)
+							r.width = desiredExtent;
+					}
+				}
+				else
+				{
+					// The rectangle needs to hang from the line's ascent and must extend far enough to accommodate the
+					// descender of the glyph (that has moved down because of superscript)
+					
+					var glyphDescent:Number = -baseStrikethroughOffset; // see assumptions above
+					baselineShift = metrics.subscriptOffset * fontSize; 
+					var lineAscent:Number = tLine.getBaselinePosition(TextBaseline.ROMAN) - tLine.getBaselinePosition(TextBaseline.ASCENT);
+					
+					desiredExtent = lineAscent + baselineShift + glyphDescent;
+					if (horizontalText)
+					{
+						if (desiredExtent > r.height)
+							r.height = desiredExtent;
+					}
+					else
+					{
+						if (desiredExtent > r.width)
+						{
+							r.x -= desiredExtent - r.width
+							r.width = desiredExtent;
+						}
+					}
+				}
+			}
+			
+			tf.backgroundManager.addRect(line, this, r, _computedFormat.backgroundColor, _computedFormat.backgroundAlpha);	 
+		 }
+		 
+		
+		/** @private
+		 * Gets the EventDispatcher associated with this FlowLeafElement.  Use the functions
+		 * of EventDispatcher such as <code>setEventHandler()</code> and <code>removeEventHandler()</code> 
+		 * to capture events that happen over this FlowLeafElement object.  The
+		 * event handler that you specify will be called after this FlowLeafElement object does
+		 * the processing it needs to do.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flash.events.EventDispatcher
+		 */
+		tlf_internal function getEventMirror():EventDispatcher
+		{
+			if (!_blockElement)
+			{
+				var para:ParagraphElement = getParagraph();
+				if (para)
+					para.getTextBlock();
+				else
+					createContentElement();
+			}
+			if (_blockElement.eventMirror == null)
+			{				
+				_blockElement.eventMirror = new EventDispatcher();
+			}
+			_hasAttachedListeners = true;
+			return (_blockElement.eventMirror);
+		}
+		
+		
+		/** @private */
+		tlf_internal function calculateStrikeThrough(textLine:TextLine, blockProgression:String, metrics:FontMetrics):Number
+		{
+			var underlineAndStrikeThroughShift:int = 0;	
+			var effectiveFontSize:Number = this.getEffectiveFontSize()
+			if (_computedFormat.baselineShift == BaselineShift.SUPERSCRIPT)
+			{
+				underlineAndStrikeThroughShift = -(metrics.superscriptOffset * effectiveFontSize);
+			} else if (_computedFormat.baselineShift == BaselineShift.SUBSCRIPT)
+			{
+				underlineAndStrikeThroughShift = -(metrics.subscriptOffset * (effectiveFontSize / metrics.subscriptScale));
+			} else {
+				underlineAndStrikeThroughShift = TextLayoutFormat.baselineShiftProperty.computeActualPropertyValue(_computedFormat.baselineShift, effectiveFontSize);
+			}
+			
+			//grab the dominantBaseline and alignmentBaseline strings
+			var domBaselineString:String = resolveDomBaseline();
+			var alignmentBaselineString:String = this.computedFormat.alignmentBaseline;
+			
+			//this value represents the position of the baseline used to align this text
+			var alignDomBaselineAdjustment:Number = textLine.getBaselinePosition(domBaselineString);
+			
+			//if the alignment baseline differs from the dominant, then we need to apply the delta between the
+			//dominant and the alignment to determine the line along which the glyphs are lining up...
+			if(alignmentBaselineString != flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE && 
+				alignmentBaselineString != domBaselineString)
+			{
+				alignDomBaselineAdjustment = textLine.getBaselinePosition(alignmentBaselineString);
+				//take the alignmentBaseline offset and make it relative to the dominantBaseline
+			}
+			
+			
+			//first, establish the offset relative to the glyph based in fontMetrics data
+			var stOffset:Number = metrics.strikethroughOffset;
+			
+			
+			//why are we using the stOffset?  Well, the stOffset effectively tells us where the mid-point
+			//of the glyph is.  By using this value, we can determine how we need to offset the underline.
+			//now adjust the value.  If it is center, then the glyphs are aligned along the ST position already
+			if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER)
+			{
+				stOffset = 0;
+			}
+			else if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP || 
+				domBaselineString == flash.text.engine.TextBaseline.ASCENT)
+			{
+				stOffset *= -2;  //if the glyphs are top or ascent, then we need to invert and double the offset
+				stOffset -= (2 * metrics.strikethroughThickness);
+			}
+			else if(domBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM || 
+				domBaselineString == flash.text.engine.TextBaseline.DESCENT)
+			{
+				stOffset *= 2; //if they're bottom, then we need to simply double it
+				stOffset += (2 * metrics.strikethroughThickness);
+			}
+			else //Roman
+			{
+				stOffset -= metrics.strikethroughThickness;
+			}
+			
+			
+			//Now apply the actual dominant baseline position to the offset
+			stOffset += (alignDomBaselineAdjustment - underlineAndStrikeThroughShift);
+			return stOffset;
+		}
+		
+		/** @private */
+		tlf_internal function calculateUnderlineOffset(stOffset:Number, blockProgression:String, metrics:FontMetrics, textLine:TextLine):Number
+		{
+			var ulOffset:Number = metrics.underlineOffset + metrics.underlineThickness;
+			var baseSTAdjustment:Number = metrics.strikethroughOffset;
+			
+			//based on the stOffset - which really represents the middle of the glyph, set the ulOffset
+			//which will always be relative.  Note that simply using the alignDomBaselineAdjustment is not enough
+			if(blockProgression != BlockProgression.RL)
+				ulOffset += (stOffset - baseSTAdjustment) + metrics.underlineThickness/2;
+			else
+			{	
+				var para:FlowElement = this.parent;
+				while(!(para is ParagraphElement))
+				{
+					para = para.parent;
+				}
+				var lowerLocale:String = para.computedFormat.locale.toLowerCase();
+				if(lowerLocale.indexOf("zh") == 0)
+				{
+					ulOffset = -ulOffset;
+					ulOffset -= (stOffset - baseSTAdjustment + (metrics.underlineThickness*2));
+				}
+				else
+					ulOffset -= (-ulOffset + stOffset + baseSTAdjustment + (metrics.underlineThickness/2));
+			}
+			
+			return ulOffset;
+		}
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			
+			var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(_blockElement)+" "+extraData);
+			
+			// TODO: eventually these tests will be valid for InlineGraphicElement elements as well
+			if (!(this is InlineGraphicElement))
+			{
+				rslt += assert(textLength != 0 || bindableElement || (parent is SubParagraphGroupElement && parent.numChildren == 1), "FlowLeafElement with zero textLength must be deleted"); 
+				rslt += assert(parent is ParagraphElement || parent is SubParagraphGroupElement, "FlowLeafElement must have a ParagraphElement or SubParagraphGroupElement parent");
+			}
+			return rslt;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/FlowValueHolder.as b/textLayout_core/src/flashx/textLayout/elements/FlowValueHolder.as
new file mode 100755
index 0000000..b215383
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/FlowValueHolder.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 flashx.textLayout.elements
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** This class extends TextLayoutFormatValueHolder and add capabilities to hold privateData and userStyles.  @private */
+	public class FlowValueHolder extends TextLayoutFormatValueHolder
+	{
+		private var _userStyles:Object;
+		private var _privateData:Object;
+		
+		public function FlowValueHolder(initialValues:FlowValueHolder = null)
+		{
+			super(initialValues);
+			initialize(initialValues);
+		}
+		
+		private function initialize(initialValues:FlowValueHolder):void
+		{
+			if (initialValues)
+			{
+				for (var s:String in initialValues.userStyles)
+					writableUserStyles()[s] = initialValues.userStyles[s];
+				for (s in initialValues.privateData)
+					writablePrivateData()[s] = initialValues.privateData[s];
+			}
+		}
+
+		private function writableUserStyles():Object
+		{ 
+			if (_userStyles == null)
+				_userStyles = new Object();
+			return _userStyles;
+		}
+			
+		public function get userStyles():Object
+		{ return _userStyles; }
+		public function set userStyles(val:Object):void
+		{ _userStyles = val; }
+
+		public function getUserStyle(styleProp:String):*
+		{ return _userStyles ? _userStyles[styleProp] : undefined; }
+		public function setUserStyle(styleProp:String,newValue:*):void
+		{
+			CONFIG::debug { assert(TextLayoutFormat.description[styleProp] === undefined,"bad call to setUserStyle"); }
+			if (newValue === undefined)
+			{
+				if (_userStyles)
+					delete _userStyles[styleProp];
+			}
+			else
+				writableUserStyles()[styleProp] = newValue;
+		}
+
+		private function writablePrivateData():Object
+		{
+			if (_privateData == null)
+				_privateData = new Object();
+			return _privateData;
+		}
+
+		public function get privateData():Object
+		{ return _privateData; }
+		public function set privateData(val:Object):void
+		{ _privateData = val; }
+
+		public function getPrivateData(styleProp:String):*
+		{ return _privateData ? _privateData[styleProp] : undefined; }
+
+		public function setPrivateData(styleProp:String,newValue:*):void
+		{
+			if (newValue === undefined)
+			{
+				if (_privateData)
+					delete _privateData[styleProp];
+			}
+			else
+				writablePrivateData()[styleProp] = newValue;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/GlobalSettings.as b/textLayout_core/src/flashx/textLayout/elements/GlobalSettings.as
new file mode 100755
index 0000000..93e4575
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/GlobalSettings.as
@@ -0,0 +1,214 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+	
+	/** Configuration that applies to all TextFlow objects.
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 */
+	public class GlobalSettings 
+	{
+		/** 
+		* Specifies the callback used for font mapping.
+		* The callback takes a <code>flash.text.engine.FontDescription</code> object and updates it as needed.
+		* 
+		* After setting a new font mapping callback, or changing the behavior of the exisiting font mapping callback, 
+		* the client must explicitly call <code>flashx.textLayout.elements.TextFlow.invalidateAllFormats</code> for each impacted text flow.
+		* This ensures that whenever a leaf element in the text flow is next recomposed, the FontDescription applied to it is recalculated, and the the callback is invoked. 
+		* 
+		* @see flash.text.engine.FontDescription FontDescription
+		* @see TextFlow.invalidateAllFormats invalidateAllFormats
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		public static function get fontMapperFunction():Function
+		{ 
+			return _fontMapperFunction; 
+		}
+		public static function set fontMapperFunction(val:Function):void
+		{
+			_fontMapperFunction = val;
+			FlowLeafElement.clearElementFormatsCache(); // clear out possibly stale mappings between computed TextLayoutFormats and ElementFormats
+		}
+		
+		private static var _fontMapperFunction:Function
+		
+		/** Controls whether the text will be visible to a search engine indexer. Defaults to <code>true</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function get enableSearch():Boolean
+		{
+			return _enableSearch;
+		}
+		public static function set enableSearch(value:Boolean):void
+		{
+			_enableSearch = value;
+		}
+		
+		private static var _enableSearch:Boolean = true;
+	
+		/** 
+		 * Specifies the callback used for changing the FontLookup based on swfcontext.  The function will be called each time an ElementFormat is computed.
+		 * It gives the client the opportunity to modify the FontLookup setting.  The function is called with two parameters an ISWFContext and an ITextLayoutFormat.
+		 * It must return a valid FontLookup.
+		 * 
+		 * @see flashx.textLayout.compose.ISWFContext
+		 * @see flashx.textLayout.formats.ITextLayoutFormat
+		 * @see flash.text.engine.ElementFormat
+		 * @see flash.text.engine.FontLookup
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function get resolveFontLookupFunction():Function
+		{ 
+			return _resolveFontLookupFunction; 
+		}
+		public static function set resolveFontLookupFunction(val:Function):void
+		{
+			_resolveFontLookupFunction = val;
+		}
+		private static var _resolveFontLookupFunction:Function
+		
+		/** Function that takes two parameters, a resource id and an optional array of parameters to substitute into the string.
+		 * The string is of form "Content {0} more content {1}".  The parameters are read from the optional array and substituted for the bracketed substrings
+		 * TLF provides a default implementation with
+		 * default strings.  Clients may replace this function with their own implementation for localization.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function get resourceStringFunction():Function
+		{ 
+			return _resourceStringFunction; 
+		}
+		public static function set resourceStringFunction(val:Function):void
+		{
+			_resourceStringFunction = val;
+		}
+		
+		private static var _resourceStringFunction:Function = defaultResourceStringFunction;
+		
+		/** @private */
+		
+		private static const resourceDict:Object = 
+		{
+			missingStringResource:			"No string for resource {0}",
+			// core errors
+			invalidFlowElementConstruct:	"Attempted construct of invalid FlowElement subclass",
+			invalidSplitAtPosition:			"Invalid parameter to splitAtPosition",
+			badMXMLChildrenArgument: 		"Bad element of type {0} passed to mxmlChildren",
+			badReplaceChildrenIndex: 		"Out of range index to FlowGroupElement.replaceChildren",
+			invalidChildType: 				"NewElement not of a type that this can be parent of",
+			badRemoveChild: 				"Child to remove not found",
+			invalidSplitAtIndex:			"Invalid parameter to splitAtIndex",
+			badShallowCopyRange: 			"Bad range in shallowCopy",
+			badSurrogatePairCopy: 			"Copying only half of a surrogate pair in SpanElement.shallowCopy",
+			invalidReplaceTextPositions:	"Invalid positions passed to SpanElement.replaceText",
+			invalidSurrogatePairSplit: 		"Invalid splitting of a surrogate pair",
+			badPropertyValue:				"Property {0} value {1} is out of range",
+			// selection/editing
+			illegalOperation:				"Illegal attempt to execute {0} operation",
+			// shared import errors
+			unexpectedXMLElementInSpan:		"Unexpected element {0} within a span",
+			unexpectedNamespace:			"Unexpected namespace {0}",
+			unknownElement: 				"Unknown element {0}",
+			unknownAttribute: 				"Attribute {0} not permitted in element {1}",
+			// html format import errors
+			malformedTag:					"Malformed tag {0}",
+			malformedMarkup: 				"Malformed markup {0}",
+			// textlayoutformat import errors
+			missingTextFlow: 				"No TextFlow to parse",
+			expectedExactlyOneTextLayoutFormat: "Expected one and only one TextLayoutFormat in {0}" 	
+		};
+		
+		/** @private */
+		tlf_internal static function defaultResourceStringFunction(resourceName:String, parameters:Array = null):String
+		{
+			var value:String = String(resourceDict[resourceName]);
+			
+			if (value == null)
+			{
+				value = String(resourceDict["missingStringResource"]);
+				parameters = [ resourceName ];
+			}
+			
+			if (parameters)
+				value = substitute(value, parameters);
+			
+			return value;
+		}
+		
+		/** @private */
+		tlf_internal static function substitute(str:String, ... rest):String
+		{
+			if (str == null) 
+				return '';
+			
+			// Replace all of the parameters in the msg string.
+			var len:uint = rest.length;
+			var args:Array;
+			if (len == 1 && rest[0] is Array)
+			{
+				args = rest[0] as Array;
+				len = args.length;
+			}
+			else
+			{
+				args = rest;
+			}
+			
+			for (var i:int = 0; i < len; i++)
+			{
+				str = str.replace(new RegExp("\\{"+i+"\\}", "g"), args[i]);
+			}
+			
+			return str;
+		}
+		
+
+		private static var _enableDefaultTabStops:Boolean = false;
+		/** 
+		 * @private Player versions prior to 10.1 do not set up any default tabStops. As a workaround, if enableDefaultTabs
+		 * is true, TLF will set up default tabStops in the case where there are no tabs defined.
+		 * 
+		 */		
+		tlf_internal static function get enableDefaultTabStops():Boolean
+		{
+			return _enableDefaultTabStops;
+		}
+		/** 
+		 * @private 
+		 */			
+		tlf_internal static function set enableDefaultTabStops(val:Boolean):void
+		{
+			_enableDefaultTabStops = val;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/IConfiguration.as b/textLayout_core/src/flashx/textLayout/elements/IConfiguration.as
new file mode 100755
index 0000000..d95a538
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/IConfiguration.as
@@ -0,0 +1,306 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.edit.SelectionFormat;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	/** Read-only interface to a configuration object.  Used by TextFlow to guarantee it has an unchangeable 
+	 * configuration once its constructed.
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface IConfiguration 
+	{
+		/** 
+		* Specifies whether the TAB key is entered as text by Text Layout Framework, or Flash Player or AIR handles it and 
+		* turns it into a tabbed panel event. 
+		*
+		* <p>Default value is <code>false</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get manageTabKey():Boolean
+
+		/** 
+		* Specifies whether the Enter / Return key is entered as text by Text Layout Framework, to split a paragraph for example,
+		* or the client code handles it. The client code might handle it by committing a form that has a default button 
+		* for that purpose, for example. 
+		*
+		* <p>Default value is <code>true</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get manageEnterKey():Boolean
+		
+		/** 
+		* Policy used for deciding whether the last line of a container fits in the container, or whether it overflows.
+		* Use the constants of the OverflowPolicy class to set this property.
+		*
+		* <p>Default value is OverflowPolicy.FIT_DESCENDERS, which fits the line in the composition area if the area
+		* from the top to the baseline fits.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see OverflowPolicy
+		*/
+		
+		function get overflowPolicy():String;
+		
+		/** 
+		* Specifies whether accessibility support is turned on or not.  If <code>true</code>, screen readers can read the TextFlow contents.
+		*
+		* <p>Default value is <code>false</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see TextFlow
+		*/
+		
+		function get enableAccessibility():Boolean;
+		
+		/** 
+		* Specifies the initial link attributes for all LinkElement objects in the text flow. These are default
+		* values for new LinkElement objects that don't specify values for these attributes.
+		*
+		* The default normal format displays the link in blue with underlining.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+		* @see FlowElement#linkNormalFormat
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		function get defaultLinkNormalFormat():ITextLayoutFormat
+		
+		/** 
+		* Specifies the initial character format attributes that apply to a link (LinkElement) in the text flow when
+		* the cursor hovers over it. These are defaults for new LinkElement objects that don't specify values
+		* for these attributes.
+		*
+		* <p>Default is <code>null</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see  FlowElement#linkHoverFormat
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		function get defaultLinkHoverFormat():ITextLayoutFormat
+		
+		/** 
+		* Specifies the active character format attributes that initially apply for all links (LinkElement objects) in the text 
+		* flow. These are defaults for new LinkElement objects that don't specify values for these attributes. 
+		*
+		* <p>Default is <code>null</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see FlowElement#linkActiveFormat 
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		* @see LinkElement
+		*/
+		
+		function get defaultLinkActiveFormat():ITextLayoutFormat
+		
+		/** 
+		* Specifies the initial format TextLayoutFormat configuration for a text flow (TextFlow object).
+		*
+		* <p>Default is <code>null</code>.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see TextFlow
+		* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+		*/
+		
+		function get textFlowInitialFormat():ITextLayoutFormat
+		
+		/** 
+		* The initial selection format (SelectionFormat) for a text flow (TextFlow) when its window has focus. 
+		* Text Layout Framework uses <code>focusedSelectionFormat</code> to draw the selection when the window is active and one of 
+		* the containers in the TextFlow has focus. You can override this format using 
+		* <code>SelectionManager.focusedSelectionFormat</code>, if desired.
+		*
+		* <p>The SelectionFormat class specifies the default values, which invert the color of the text and its background.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#focusedSelectionFormat SelectionManager.focusedSelectionFormat
+		* @see TextFlow
+		*/
+		
+		function get focusedSelectionFormat():SelectionFormat
+		
+		/** 
+		* The initial selection format that Text Layout Framework uses to draw the selection when the window is active but none of the containers
+		* in the TextFlow have focus. You can override this format using <code>SelectionManager.unfocusedSelectionFormat</code>, if desired.
+		*
+		* <p>If you do not override <code>unfocusedSelectionFormat</code> the SelectionFormat values used are:</p>
+		*
+		* <ul>
+		*   <li><code>color = 0xffffff</code> (white)</li>
+		*   <li><code>alpha = 0</code></li>
+		*   <li><code>blendMode = flash.display.BlendMode.DIFFERENCE</code></li>
+		* </ul>
+		* <p>The result is no selection is displayed.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#unfocusedSelectionFormat SelectionManager.unfocusedSelectionFormat
+		* @see TextFlow
+		*/
+		
+		function get unfocusedSelectionFormat():SelectionFormat		
+		
+		/** 
+		* The initial selection format (SelectionFormat) for a text flow (TextFlow) when its window is inactive. Text Layout Framework uses 
+		* <code>inactiveSelectionFormat</code> for drawing the selection when the window is inactive. You can override 
+		* this format using <code>SelectionManager.inactiveSelectionFormat</code>, if desired.
+		*
+		* <p>If you do not override <code>unfocusedSelectionFormat</code> the SelectionFormat values used are:</p> 
+		* <ul>
+		*   <li><code>color = 0xffffff</code> (white)</li>
+		*   <li><code>alpha = 0</code></li>
+		*   <li><code>blendMode = flash.display.BlendMode.DIFFERENCE</code></li>
+		* </ul>
+		* <p>The result is no selection is displayed.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*
+		* @see flashx.textLayout.edit.SelectionFormat SelectionFormat
+		* @see flashx.textLayout.edit.SelectionManager#inactiveSelectionFormat SelectionManager.inactiveSelectionFormat
+		* @see TextFlow
+		*/
+		
+		function get inactiveSelectionFormat():SelectionFormat		
+		
+		/** 
+		* Specifies a timed delay between one scroll and the next to prevent scrolling from going 
+		* too fast. This value specifies what the delay is in milliseconds. The default value is 35.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get scrollDragDelay():Number
+		
+		/** Specifies the default number of pixels to scroll when the user initiates auto scrolling by dragging 
+		* the selection. Default value is 20.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get scrollDragPixels():Number
+		
+		/**
+		* Specifies the default percentage of the text flow to scroll for page scrolls. Default value is
+		* 7.0 / 8.0, or .875.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get scrollPagePercentage(): Number
+		
+		/** Specifies the default number of pixels to scroll for Mouse wheel events. Default value is 20.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get scrollMouseWheelMultiplier(): Number
+		
+		/** Specifies the type of flow composer to attach to a new TextFlow object by default. Default value is StandardFlowComposer.
+		*
+		* @see flashx.textLayout.compose.StandardFlowComposer StandardFlowComposer
+		* @see flashx.textLayout.elements.TextFlow TextFlow
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		
+		function get flowComposerClass():Class
+		
+		/** Requests that the process of composing text release line creation data after composing each paragraph.  
+		* This request saves memory but slows down the composing process.
+		*
+		* <p>Default value is <code>false</code>.</p>
+		*
+		* @see flashx.textLayout.compose.StandardFlowComposer StandardFlowComposer
+		* @see flash.text.engine.TextBlock#releaseLineCreationData() TextBlock.releaseLineCreationData()
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		function get releaseLineCreationData():Boolean;
+		
+		/** Specifies the callback used for resolving an inline graphic element.
+		* The callback takes a <code>flashx.textLayout.elements.InlineGraphicElement</code> object and returns
+		* the value to be used as the element's <code>flashx.textLayout.elements.InlineGraphicElement#source</code>.
+		* 
+		* This callback provides the mechanism to delay providing an inline graphic element's source until just before it is composed.
+		* <p><strong>Note:</strong> this callback will be invoked only if a 
+		* placeholder source of String type is already set. Moreover, it may be invoked
+		* multiple times. </p>
+		* 
+		* @see flashx.textLayout.elements.InlineGraphicElement InlineGraphicElement
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+		function get inlineGraphicResolverFunction():Function;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/IFormatResolver.as b/textLayout_core/src/flashx/textLayout/elements/IFormatResolver.as
new file mode 100755
index 0000000..f1780c8
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/IFormatResolver.as
@@ -0,0 +1,86 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	/** Interface to a format resolver. An implementation allows you to attach a styling mechanism of your choosing, such as
+	 *  Flex CSS styling and named styles, to a TextFlow.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 * 
+	 * @see flashx.textLayout.elements.TextFlow#formatResolver TextFlow.formatResolver
+	 */
+	 
+	public interface IFormatResolver 
+	{
+		/** Invalidates any cached formatting information for a TextFlow so that formatting must be recomputed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		function invalidateAll(textFlow:TextFlow):void;
+		
+		/** Invalidates cached formatting information on this element because, for example, the <code>parent</code> changed, 
+		 *  or the <code>id</code> or the <code>styleName</code> changed. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	  	 * @langversion 3.0*/
+	  	 
+		function invalidate(target:Object):void;
+		
+		/** Given a FlowElement or ContainerController object, return any format settings for it.
+		 *
+		 * @return format settings for the specified object.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+	 	 
+		function resolveFormat(target:Object):ITextLayoutFormat;
+		
+		/** Given a FlowElement or ContainerController object and the name of a format property, return the format value
+		 * or <code>undefined</code> if the value is not found.
+		 *
+		 * @return the value of the specified format for the specified object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		function resolveUserFormat(target:Object,userFormat:String):*;
+		
+		/** Returns the format resolver when a TextFlow is copied.
+		 *
+		 * @return the format resolver for the copy of the TextFlow.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		function getResolverForNewFlow(oldFlow:TextFlow,newFlow:TextFlow):IFormatResolver;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElement.as b/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElement.as
new file mode 100755
index 0000000..5d25adc
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElement.as
@@ -0,0 +1,1081 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements 
+{
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.display.Loader;
+	import flash.display.LoaderInfo;
+	import flash.display.MovieClip;
+	import flash.display.Shape;
+	import flash.display.Sprite;
+	import flash.events.ErrorEvent;
+	import flash.events.Event;
+	import flash.events.IOErrorEvent;
+	import flash.geom.Rectangle;
+	import flash.net.URLRequest;
+	import flash.system.Capabilities;
+	import flash.text.engine.FontMetrics;
+	import flash.text.engine.GraphicElement;
+	import flash.text.engine.TextBaseline;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextRotation;
+	
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.JustificationRule;
+	import flashx.textLayout.property.EnumStringProperty;
+	import flashx.textLayout.property.NumberOrPercentOrEnumProperty;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	/** The InlineGraphicElement class handles graphic objects that display inline in the text. 
+	 * 
+	 * <p>You can embed a graphic or any DisplayObject or specify a URl for the location of the graphic. 
+	 * The <code>height</code> and <code>width</code> properties of InlineGraphicElement control the actual size 
+	 * of the graphic to display.  These values also control how much space to allocate
+	 * for the graphic in the TextLine object that contains the graphic.
+	 * The <code>height</code> and <code>width</code> properties each can be one of:</p>
+	 * <ol>
+	 * <li>A number of pixels</li>
+	 * <li>A percent of the measured size of the image</li>
+	 * <li>The constant, "auto", which computes the size (Default value)</li>
+	 * </ol>
+	 * There are three properties, or accessors, pertaining to the width and height of a graphic:
+	 * <ul>
+	 * <li>The <code>width</code> and <code>height</code> properties</li>
+	 * <li>The <code>measuredWidth</code> and <code>measuredHeight</code> properties, which are the width or height of the graphic at load time</li>
+	 * <li>The <code>actualWidth</code> and <code>actualHeight</code> properties, which are the actual display and compose width and height of the graphic as computed from <code>width</code> or <code>height</code> and <code>measuredWidth</code> or <code>measuredHeight</code></li>
+	 * </ul>
+	 * <p>The values of the <code>actualWidth</code> and <code>actualHeight</code> properties are always zero until the graphic 
+	 * is loaded.</p>
+	 *
+	 * <p>If <code>source</code> is specified as a URI, the graphic is loaded asynchronously. If it's a DisplayObject, TextLayout uses the <code>width</code> and 
+	 * <code>height</code> at the time the graphic is set into the InlineGraphicElement object as <code>measuredHeight</code> and <code>measuredWidth</code>; 
+	 * its width and height are read immediately.</p>
+	 * <p><strong>Notes</strong>: For graphics that are loaded asynchronously the user must listen for a 
+	 * StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE event on the TextFlow and call <code>IFlowComposer.updateAllControllers()</code> to have the 
+	 * graphic appear. The value of <code>measuredWidth</code> and <code>measuredHeight</code> for graphics that are in the 
+	 * process of loading is zero.</p>
+	 *
+	 * <p>Some inline graphics are animations or videos that possibly have audio. They begin to run the first time they are composed after they finish loading.  
+	 * They don't stop running until the flowComposer on the TextFlow is set to null.  At that time they are stopped and unloaded.</p>
+	 * 
+	 * The following restrictions apply to InLineGraphicElement objects:
+	 * <ol>
+	 * 	<li>On export of TLFMarkup, source is converted to a string. If the graphic element is 
+	 *		a class, the Text Layout Framework can't export it properly</li>.
+	 *	<li>When doing a copy/paste operation of an InlineGraphicElement, if source can't be 
+	 * 		used to create a new InLineGraphicElement, it won't be pasted.  For example if 
+	 *		source is a DisplayObject, or if the graphic is set directly, it can't be 
+	 *		duplicated.  Best results are obtained if the source is the class of an embedded graphic 
+	 * 		though that doesn't export/import.</li>
+	 * 	<li>InLineGraphicElement objects work in the factory (TextFlowTextLineFactory) only if 
+	 * 		the source is a class or if you explicitly set the graphic to a loaded graphic. 
+	 * 		InlineGraphic objects that require delayed loads generally do not show up.</li>
+	 * </ol>
+	 * @includeExample examples\InlineGraphicElementExample.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see #actualHeight
+	 * @see #actualWidth
+	 * @see flash.display.DisplayObject DisplayObject
+	 * @see flashx.textLayout.compose.IFlowComposer#updateAllControllers()
+	 * @see flashx.textLayout.events.StatusChangeEvent StatusChangeEvent
+	 * @see TextFlow
+	 */
+	public final class InlineGraphicElement extends FlowLeafElement
+	{	
+		private var _source:Object;
+		
+		private var _graphic:DisplayObject;
+		
+		private var _elementWidth:Number;
+		private var _elementHeight:Number;
+
+		// internal status of the graphic.  there are more status here than publicly shown
+		private var _graphicStatus:Object;
+		
+		// set when its ok - must delay until on the stage for dynamically loaded images
+		private var okToUpdateHeightAndWidth:Boolean;
+		
+		private var _width:*;
+		private var _height:*;
+		
+		// stash away the actual width and height of the graphic
+		private var _measuredWidth:Number;
+		private var _measuredHeight:Number;
+		
+		private var _float:*;
+
+		/** Constructor - create new InlineGraphicElement object
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function InlineGraphicElement():void
+		{
+			super();
+			// The width/height on the FE.fe don't actually take until the InlineGraphicElement is loaded.
+			okToUpdateHeightAndWidth = false;
+			_measuredWidth = 0;
+			_measuredHeight = 0;
+			internalSetWidth(undefined);
+			internalSetHeight(undefined);
+			_float = floatPropertyDefinition.defaultValue;
+			_graphicStatus = InlineGraphicElementStatus.LOAD_PENDING;
+			setTextLength(1);
+			_text = String.fromCharCode(0xFDEF);
+		}
+		
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			if (_blockElement)
+				return;
+				
+			var graphicElement:GraphicElement = new GraphicElement();			
+			_blockElement = graphicElement;
+			CONFIG::debug { Debugging.traceFTECall(_blockElement,null,"new GraphicElement()"); }
+			_blockElement.textRotation = String(rotationPropertyDefinition.defaultValue)
+			CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"textRotation",String(rotationPropertyDefinition.defaultValue)); }
+			graphicElement.elementHeight = (_float != Float.NONE) ? 0 : elementHeight;
+			CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementHeight",graphicElement.elementHeight); }
+			graphicElement.elementWidth = (_float != Float.NONE) ? 0 : elementWidth;
+			CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"elementWidth",graphicElement.elementWidth); }
+			graphicElement.graphic = (_float != Float.NONE) ? new Sprite() : graphic;
+			CONFIG::debug { Debugging.traceFTEAssign(graphicElement,"graphic",graphic); }	// needs float fix
+			super.createContentElement();
+	//		trace("text is ", _blockElement.rawText.charCodeAt(0), "length", _blockElement.rawText.length);
+			_text = null;
+		}
+		
+		/** @private */
+		override tlf_internal function canReleaseContentElement():Boolean
+		{
+			return false;
+		}
+		
+		/** @private */
+		override tlf_internal function releaseContentElement():void
+		{
+			if (_blockElement == null || !canReleaseContentElement())
+				return;
+			_text = String.fromCharCode(0xFDEF);		// echo text property we get from FTE
+			super.releaseContentElement();
+		}
+		
+		// internal values for _graphicStatus.  It can also be an error code.
+		/** load initiated */
+		static private const LOAD_INITIATED:String = "loadInitiated";
+		/** public status string for open event received status.  @see flash.display.LoaderInfo.Events.open */
+		static private const OPEN_RECEIVED:String = "openReceived";
+		/** load complete received status.  @see flash.display.LoaderInfo.Events.open */
+		static private const LOAD_COMPLETE:String = "loadComplete";
+		/** loaded from embed */
+		static private const EMBED_LOADED:String = "embedLoaded";
+		/** specified as a DisplayObject */
+		static private const DISPLAY_OBJECT:String = "displayObject";
+		/** null graphic */
+		static private const NULL_GRAPHIC:String = "nullGraphic";
+		
+		
+		private function getGraphicElement():GraphicElement
+		{ 
+			if (!_blockElement)
+				createContentElement();
+			return GraphicElement(_blockElement); 
+		}
+		
+		private static var isMac:Boolean = (Capabilities.os.search("Mac OS") > -1);				
+		
+		/** The embedded graphic. 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function get graphic():DisplayObject
+		{
+			return _graphic;
+		}
+		private function setGraphic(value:DisplayObject):void
+		{
+			if (_blockElement)
+			{
+				// Update the graphicElement to match the new graphic value. If it's a float,
+				// we set it to a placeholder in the ge.graphic in order to be able to navigate
+				// to the element.  Without it, the FTE model will remove the atom and selection will not be
+				// possible. - gak 12.12.08
+				GraphicElement(_blockElement).graphic = (_float != Float.NONE) ? new Sprite() : value;
+				CONFIG::debug { Debugging.traceFTEAssign(_blockElement,"graphic",GraphicElement(_blockElement).graphic); }
+			}
+
+			_graphic = value;
+		// I think this should do a model change. But it will break paste because when we paste we do a reimport,
+		// which will cause a delayed update, which will bump the generation number *after* the command. Which 
+		// will cause undo of the command not to work.
+		//	modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+		}
+		
+		/** Width used by composition for laying out text around the graphic. @private */
+		tlf_internal function get elementWidth():Number
+		{
+			return _elementWidth;			
+		}
+		/** Width used by composition for laying out text around the graphic. @private */
+		tlf_internal function set elementWidth(value:Number):void
+		{
+			if (_blockElement)
+			{
+				GraphicElement(_blockElement).elementWidth = (_float != Float.NONE) ? 0 : value;
+				CONFIG::debug { Debugging.traceFTEAssign(GraphicElement(_blockElement),"elementWidth",GraphicElement(_blockElement).elementWidth); }
+				
+			}
+
+			 _elementWidth = value;
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength,true,false);
+		}
+		
+		/** Height used by composition for laying out text around the graphic. @private */
+		tlf_internal function get elementHeight():Number
+		{
+			return _elementHeight;			
+		}
+		/** Height used by composition for laying out text around the graphic. @private */
+		tlf_internal function set elementHeight(value:Number):void
+		{
+			if (_blockElement)
+			{
+				GraphicElement(_blockElement).elementHeight = (_float != Float.NONE) ? 0 : value;	
+				CONFIG::debug { Debugging.traceFTEAssign(GraphicElement(_blockElement),"elementHeight",GraphicElement(_blockElement).elementHeight); }
+			}
+			_elementHeight = value;
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength,true,false);
+		}
+		
+		/** Definition of the height property @private */
+		static tlf_internal const heightPropertyDefinition:NumberOrPercentOrEnumProperty = new NumberOrPercentOrEnumProperty("height", FormatValue.AUTO, false, null, 0, 32000, "0%", "1000000%", FormatValue.AUTO );
+		
+		/** Definition of the width property @private */
+		static tlf_internal const widthPropertyDefinition:NumberOrPercentOrEnumProperty = new NumberOrPercentOrEnumProperty("width", FormatValue.AUTO, false, null, 0, 32000, "0%", "1000000%", FormatValue.AUTO );
+		
+		/** Disabled due to player bug.  @private */
+		static tlf_internal const rotationPropertyDefinition:EnumStringProperty = new EnumStringProperty("rotation", TextRotation.ROTATE_0, false, null, 
+			TextRotation.ROTATE_0, TextRotation.ROTATE_90, TextRotation.ROTATE_180, TextRotation.ROTATE_270);		
+		
+		/** Definition of the float property @private */
+		static tlf_internal const floatPropertyDefinition:EnumStringProperty = new EnumStringProperty("float", Float.NONE, false, null, 
+			 Float.NONE, Float.LEFT, Float.RIGHT);
+			
+		/** The current status of the image. On each status change the owning TextFlow sends a StatusChangeEvent.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @return one of LOAD_PENDING, LOADING, SIZE_PENDING, READY, ERROR
+		 * @see flashx.textLayout.elements.InlineGraphicElementStatus
+		 * @see flashx.textLayout.events.StatusChangeEvent
+		 */
+		 
+		public function get status():String
+		{
+			switch(_graphicStatus)
+			{
+				case LOAD_INITIATED:
+				case OPEN_RECEIVED:
+					return InlineGraphicElementStatus.LOADING;
+				case LOAD_COMPLETE:
+				case EMBED_LOADED:
+				case DISPLAY_OBJECT:
+				case NULL_GRAPHIC:
+					return InlineGraphicElementStatus.READY;
+				case InlineGraphicElementStatus.LOAD_PENDING:
+				case InlineGraphicElementStatus.SIZE_PENDING:
+					return String(_graphicStatus);
+			}
+			CONFIG::debug { assert(_graphicStatus is ErrorEvent,"unexpected _graphicStatus"); }
+			return InlineGraphicElementStatus.ERROR; 
+		}
+		
+		private function changeGraphicStatus(stat:Object):void
+		{
+			var oldStatus:String = status;
+			_graphicStatus = stat;
+			var newStatus:String = status;
+			if (oldStatus != newStatus || stat is ErrorEvent)
+			{
+				var tf:TextFlow = getTextFlow();
+				if (tf)
+				{
+					if (newStatus == InlineGraphicElementStatus.SIZE_PENDING)
+						tf.processAutoSizeImageLoaded(this);
+					tf.dispatchEvent(new StatusChangeEvent(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, false, false, this, newStatus, stat as ErrorEvent));
+				}
+			}
+		}
+				
+		/** The width of the graphic. The value can be 'auto', a number of pixels or a percent of the measured width of the image.
+		 * 
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from 0 to 32000.</p>
+		 * <p>Legal values as a percent are numbers from 0 to 1000000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined or "inherit" the InlineGraphicElement will use the default value of "auto".</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #actualWidth
+	 	 * @see #measuredWidth
+	 	 */
+		public function get width():*
+		{ return _width; }
+		public function set width(w:*):void
+		{ 
+			internalSetWidth(w);
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+		}
+		
+		/** The natural width of the graphic. This is the width of the graphic at load time.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see #actualWidth
+	 	* @see #width
+	 	*/
+	 	
+		public function get measuredWidth():Number
+		{ return _measuredWidth; }
+		
+		/** The actual width in effect. This is the display and compose width that's computed from the
+		* <code>width</code> and <code>measuredWidth</code> properties.
+		*
+		* <p>The values of the <code>actualWidth</code>property are computed according to the 
+		* following table:</p>
+		* <table class="innertable" width="100%">
+		* <tr>
+		*   <th>width property</th> 
+		*   <th>actualWidth</th>
+		* </tr>
+		* <tr>
+		*   <td>auto</td>
+		*   <td>measuredWidth</td>
+		* </tr>
+		* <tr>
+		*   <td>w a Percent</td>
+		*   <td>w percent of measuredWidth</td>
+		* </tr>
+		* <tr>
+		*   <td>w a Number</td>
+		*   <td>w</td>
+		* </tr>
+		* </table>
+		*
+		* <p><strong>Notes</strong>: If the inline graphic is a DisplayObject, its width and height are read immediately.
+		* If <code>measuredWidth</code> or <code>measuredHeight</code> are zero, then any auto calculations that would cause a divide by zero sets the result to zero.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see #measuredWidth
+	 	* @see #width
+	 	*
+	 	*/
+	 	
+		public function get actualWidth():Number
+		{ return elementWidth; }
+		
+		private function widthIsComputed():Boolean
+		{ return internalWidth is String; }
+		
+		private function get internalWidth():Object
+		{ return _width === undefined ? widthPropertyDefinition.defaultValue : _width; }		
+
+		private function computeWidth():Number
+		{
+			CONFIG::debug { assert(widthIsComputed(),"bad call to InlineGraphicElement.computeWidth"); }
+			if (internalWidth == FormatValue.AUTO)
+			{
+				if (internalHeight == FormatValue.AUTO)
+					return _measuredWidth;
+				if (_measuredHeight == 0 || _measuredWidth == 0)
+					return 0;
+				// can't rely on height being calculated yet
+				var effHeight:Number = heightIsComputed() ? computeHeight(): Number(internalHeight);
+				return effHeight/_measuredHeight * _measuredWidth;
+			}
+			return widthPropertyDefinition.computeActualPropertyValue(internalWidth,_measuredWidth); 
+		}
+		
+		private function internalSetWidth(w:*):void
+		{
+			_width = widthPropertyDefinition.setHelper(width,w);
+			elementWidth = widthIsComputed() ? 0 : Number(internalWidth);
+			if (okToUpdateHeightAndWidth && graphic)
+			{
+				if (widthIsComputed())
+					elementWidth =  computeWidth();
+				graphic.width = elementWidth;
+				CONFIG::debug { Debugging.traceFTEAssign(graphic,"width",elementWidth); }
+				if (internalHeight == FormatValue.AUTO)
+				{
+					elementHeight =  computeHeight();
+					graphic.height = elementHeight;
+					CONFIG::debug { Debugging.traceFTEAssign(graphic,"height",elementHeight); }
+				}
+			}
+		}
+
+		/** The height of the image. May be 'auto', a number of pixels or a percent of the measured height. 
+		 *
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from 0 to 32000.</p>
+		 * <p>Legal values as a percent are numbers from 0 to 1000000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined or "inherit" the InlineGraphicElement will use the default value of "auto".</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		  * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #actualHeight
+	 	 * @see #measuredHeight
+	 	 */
+		public function get height():*
+		{ return _height; }
+		public function set height(h:*):void
+		{
+			internalSetHeight(h);
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+		}
+		
+		private function get internalHeight():Object
+		{ return _height === undefined ? heightPropertyDefinition.defaultValue : _height; }
+		
+		/** @private - prototype phase only */
+		tlf_internal function get float():*
+		{
+			return _float;
+		}
+		/** @private - prototype phase only */
+		tlf_internal function set float(value:*):*
+		{
+			if (value === undefined)
+				value = floatPropertyDefinition.defaultValue;
+			value = floatPropertyDefinition.setHelper(float, value) as String;
+			if (_float != value)
+			{
+				var origWasInline:Boolean = _float == Float.NONE;
+				_float = value;
+				
+				if (_float != Float.NONE)		// it's float; move variables from fte back to floating so fte won't see them
+				{
+					//only apply the graphicElement width and height if the original graphicElement was not a placeHolder
+					//failure to do so will result in a 0 width/height element.
+					if(origWasInline && _blockElement)
+					{
+						var graphicElement:GraphicElement = GraphicElement(_blockElement);
+						setGraphic(graphicElement.graphic);
+						elementWidth = graphicElement.elementWidth;
+						elementHeight = graphicElement.elementHeight;
+					}
+				}
+				else 	// it's inline: move varibles back from floating to where fte will see them
+				{
+					_graphic.x = 0;		// clear out whatever repositioning was done by floats code
+					_graphic.y = 0;
+					setGraphic (_graphic);
+					elementWidth = _elementWidth;
+					elementHeight = _elementHeight;					
+				}
+				modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+			}					
+		}
+		
+		/** The natural height of the graphic. This is the height of the graphic at load time.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	* 
+	 	* @see #actualHeight
+	 	* @see #height
+	 	*/
+	 	
+		public function get measuredHeight():Number
+		{ return _measuredHeight; }
+			
+		/** The actual height in effect. This is the display and compose height that's computed from the
+		* <code>height</code> and <code>measuredHeight</code> properties.
+		*
+		* <p>The values of the <code>actualHeight</code> property are computed according to the following table:</p>
+		* <table class="innertable" width="100%">
+		* <tr>
+		*   <th>height property</th>
+		*   <th>actualHeight</th>
+		* </tr>
+		* <tr>
+		*   <td>auto</td>
+		*   <td>measuredheight</td>
+		* </tr>
+		* <tr>
+		*   <td>h a Percent</td>
+		*   <td>h percent of measuredheight</td>
+		* </tr>
+		* <tr>
+		*   <td>h a Number</td>
+		*   <td>h</td>
+		* </tr>
+		* </table>
+		* <p><strong>Notes</strong>: If the inline graphic is a DisplayObject, its width and height are read immmediately.
+		* If <code>measuredWidth</code> or <code>measuredHeight</code> are zero, then any auto calculations that would cause a divide by zero sets the result to zero.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see #height
+	 	* @see #measuredHeight
+	 	*/
+	 	
+		public function get actualHeight():Number
+		{ return elementHeight; }
+		
+		private function heightIsComputed():Boolean
+		{ return internalHeight is String; }
+		
+		private function computeHeight():Number
+		{
+			CONFIG::debug { assert(heightIsComputed(),"bad call to InlineGraphicElement.computeWidth"); }
+			if (internalHeight == FormatValue.AUTO)
+			{
+				if (internalWidth == FormatValue.AUTO)
+					return _measuredHeight;
+				if (_measuredHeight == 0 || _measuredWidth == 0)
+					return 0;
+				// can't rely on width being calculated yet
+				var effWidth:Number = widthIsComputed() ? computeWidth(): Number(internalWidth);
+				return effWidth/_measuredWidth * _measuredHeight;
+			}
+			return heightPropertyDefinition.computeActualPropertyValue(internalHeight,_measuredHeight); 
+		}
+		
+		private function internalSetHeight(h:*):void
+		{
+			_height = heightPropertyDefinition.setHelper(height,h);
+			elementHeight = heightIsComputed() ? 0 : Number(internalHeight);
+			if (okToUpdateHeightAndWidth && graphic != null)
+			{
+				if (heightIsComputed())
+					elementHeight =  computeHeight();
+				graphic.height = elementHeight;
+				CONFIG::debug { Debugging.traceFTEAssign(graphic,"height",elementHeight); }
+
+				if (internalWidth == FormatValue.AUTO)
+				{
+					elementWidth =  computeWidth();
+					graphic.width = elementWidth;
+					CONFIG::debug { Debugging.traceFTEAssign(graphic,"width",elementWidth); }
+				}
+			}
+		}
+		
+		private function loadCompleteHandler(e:Event):void
+		{			
+			CONFIG::debug { Debugging.traceFTECall(null,null,"loadCompleteHandler",this); }
+			removeDefaultLoadHandlers();
+			CONFIG::debug { assert(okToUpdateHeightAndWidth == false,"invalid call to loadCompleteHandler"); }
+			okToUpdateHeightAndWidth = true;
+			
+			var g:DisplayObject = graphic;
+			_measuredWidth = g.width;
+			_measuredHeight = g.height;
+			
+			if (!widthIsComputed())
+				g.width  = elementWidth;
+			if (!heightIsComputed())
+				g.height = elementHeight;
+				
+			if (e is IOErrorEvent)
+				changeGraphicStatus(e);
+			else if (widthIsComputed() || heightIsComputed())
+			{
+				g.visible = false;
+				// triggers a delayedElementUpdate
+				changeGraphicStatus(InlineGraphicElementStatus.SIZE_PENDING);
+			}
+			else
+				changeGraphicStatus(LOAD_COMPLETE);
+		}
+				
+		private function openHandler(e:Event):void
+		{
+			changeGraphicStatus(OPEN_RECEIVED);
+		}
+		
+		private function addDefaultLoadHandlers(loader:Loader):void
+		{
+			var loaderInfo:LoaderInfo = loader.contentLoaderInfo;
+			CONFIG::debug { Debugging.traceFTECall(loaderInfo,loader,"contentLoaderInfo"); }
+			
+			loaderInfo.addEventListener(Event.OPEN, openHandler, false, 0, true);
+			CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",Event.OPEN, "openHandler", false, 0, true); }
+			loaderInfo.addEventListener(Event.COMPLETE,loadCompleteHandler,false,0,true);	
+			CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",Event.COMPLETE, "loadCompleteHandler", false, 0, true); }
+			loaderInfo.addEventListener(IOErrorEvent.IO_ERROR,loadCompleteHandler,false,0,true);	
+			CONFIG::debug { Debugging.traceFTECall(null,loaderInfo,"addEventListener",IOErrorEvent.IO_ERROR, "loadCompleteHandler", false, 0, true); }
+		}
+		
+		private function removeDefaultLoadHandlers():void
+		{
+			var loader:Loader = Loader(graphic);
+			CONFIG::debug{ assert(loader != null,"bad call to removeDefaultLoadHandlers"); }
+			loader.contentLoaderInfo.removeEventListener(Event.OPEN, openHandler);
+			loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
+			loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadCompleteHandler);
+		}
+		
+		/** Sets the source for the graphic. 
+		 * 
+		 * The value can be either a String that is interpreted as a URI, a Class that's interpreted as the class of an 
+		 * embeddded DisplayObject, a DisplayObject instance, or a URLRequest. Creates a DisplayObject and,
+		 * if the InlineGraphicElement object is added into a ParagraphElement in a TextFlow object, causes it to appear
+		 * inline in the text.
+		 *
+		 * @includeExample examples\InlineGraphicElement_sourceExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function get source():Object
+		{
+			return _source;
+		}
+		public function set source(value:Object):void
+		{
+			stop(true);
+			_source = value;
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+			changeGraphicStatus(InlineGraphicElementStatus.LOAD_PENDING);
+		}
+	
+		/** @private */
+		tlf_internal override function applyDelayedElementUpdate(textFlow:TextFlow,okToUnloadGraphics:Boolean,hasController:Boolean):void
+		{
+			CONFIG::debug { assert(textFlow != null,"ILG:applyDelayedElementUpdate: null textFlow"); }		
+			if (_graphicStatus == InlineGraphicElementStatus.LOAD_PENDING)
+			{
+				// trace("FEX LOADING", this.toString());
+				if (hasController)
+				{
+					var source:Object = _source;
+					if (source is String)
+					{
+						var inlineGraphicResolver:Function = textFlow.configuration.inlineGraphicResolverFunction;
+						if (inlineGraphicResolver != null)
+							source = inlineGraphicResolver(this);
+					}
+					
+					var elem:DisplayObject;
+					if (source is String || source is URLRequest)
+					{
+						okToUpdateHeightAndWidth = false;
+						var loader:Loader = new Loader();
+						CONFIG::debug { Debugging.traceFTECall(loader,null,"new Loader()"); }
+
+						// set the width/height on COMPLETE or IOError
+						addDefaultLoadHandlers(loader);
+						if (source is String)
+						{
+ 							var myPattern:RegExp = /\\/g;  							
+							var src:String = source as String;
+							src = src.replace(myPattern, "/");
+							//workaround for Watson bug 1896186.  FlashPlayer requres that file
+							//names be encoded on Macintosh, but not on Windows.  Grouped this
+							//bug with FlashPlayer Watson bug 1899687
+							var pictURLReq:URLRequest;
+							if (isMac)
+							{
+								pictURLReq = new URLRequest(encodeURI(src));
+								CONFIG::debug { Debugging.traceFTECall(pictURLReq,null,"new URLRequest",encodeURI(src)); }
+							}
+							else
+							{
+								pictURLReq = new URLRequest(src);	
+								CONFIG::debug { Debugging.traceFTECall(pictURLReq,null,"new URLRequest",src); }									
+							}					
+							loader.load(pictURLReq);
+							CONFIG::debug { Debugging.traceFTECall(null,loader,"load",pictURLReq); }									
+						}
+						else
+							loader.load(URLRequest(source));
+								
+						setGraphic(loader);		
+						changeGraphicStatus(LOAD_INITIATED);
+					}
+					else if (source is Class)	// value is class --> it is an Embed
+					{
+						var cls:Class = source as Class;
+						elem = DisplayObject(new cls());
+						changeGraphicStatus(EMBED_LOADED);
+					}
+					else if (source is DisplayObject)
+					{
+						elem = DisplayObject(source);
+						changeGraphicStatus(DISPLAY_OBJECT);
+					}
+					else
+					{
+						elem = new Shape();
+						changeGraphicStatus(NULL_GRAPHIC);
+					}
+					
+					// complete setup of width and height
+					if (_graphicStatus != LOAD_INITIATED)
+					{
+						okToUpdateHeightAndWidth = true;
+						_measuredWidth = elem ? elem.width : 0;
+						_measuredHeight = elem ? elem.height : 0;
+
+						if (widthIsComputed())
+						{
+							if (elem)
+							{
+								elem.width = elementWidth = computeWidth();
+								CONFIG::debug { Debugging.traceFTEAssign(elem,"width",elem.width); }
+							}
+							else
+								elementWidth = 0;
+						}
+						else
+						{
+							elem.width = Number(width);
+							CONFIG::debug { Debugging.traceFTEAssign(elem,"width",elem.width); }
+						}
+							
+						if (heightIsComputed())
+						{
+							if (elem)
+							{
+								elem.height = elementHeight = computeHeight();
+								CONFIG::debug { Debugging.traceFTEAssign(elem,"height",elem.height); }
+							}
+							else
+								elementHeight = 0;
+						}
+						else
+						{
+							elem.height = Number(height);
+							CONFIG::debug { Debugging.traceFTEAssign(elem,"height",elem.height); }
+						}
+							
+						setGraphic(elem);
+					}
+				}
+			}
+			else
+			{
+				if (_graphicStatus == InlineGraphicElementStatus.SIZE_PENDING)
+				{
+					// this is width/height auto case hasn't been set yet - the graphic is hidden!
+					updateAutoSizes();
+					graphic.visible = true;
+					changeGraphicStatus(LOAD_COMPLETE);
+				}
+				if (!hasController)
+				{
+					// shutdown the audio on any movie clips
+					stop(okToUnloadGraphics);
+				}
+			}
+		}
+		
+		/** @private This API supports the inputmanager */
+		tlf_internal override function updateForMustUseComposer(textFlow:TextFlow):Boolean
+		{ 
+			applyDelayedElementUpdate(textFlow,false,true);
+			return status != InlineGraphicElementStatus.READY;
+		}
+		
+		/** This function updates the size of the graphic element when the size is expressed as a percentage of the graphic's actual size. */
+		private function updateAutoSizes():void
+		{
+			// some discussion about making this function public.  the idea is that if the graphic
+			// changes size the client can force it to recompute.  however the measuredWidth and measuredHeight
+			// of the graphic doesn't really exist anywhere.
+			
+			// when public can only call ths for certain values of _graphicStatus
+			// if (_graphicStatus == NULL_GRAPHIC || _graphicStatus == LOAD_INITIATED || _graphicStatus == OPEN_RECEIVED)
+			//	return;
+				
+			// if (widthIsComputed() || heightIsComputed())	
+			{
+				if (widthIsComputed())
+				{
+					elementWidth = computeWidth();
+					graphic.width = elementWidth;
+				}
+				if (heightIsComputed())
+				{
+					elementHeight = computeHeight();
+					graphic.height = elementHeight;
+				}
+			}
+		}
+		
+		
+		/** stop if its a movieclip */
+		private function stop(okToUnloadGraphics:Boolean):Boolean
+		{
+			
+			// watch for changing the source while we've got an event listener on the current graphic
+			// if so cancel the load and remove the listeners
+			if (_graphicStatus == OPEN_RECEIVED || _graphicStatus == LOAD_INITIATED)
+			{
+				try
+				{
+					Loader(graphic).close();	// cancels in process load
+				}
+				catch (e:Error)
+				{ /* ignore */ }
+				removeDefaultLoadHandlers();
+			}
+
+			// shutdown any running movieclips - this graphic will no longer be referenced
+			// for graphics that the client has passed us - just ignore they own the responsibliity
+			if (_graphicStatus != DISPLAY_OBJECT)
+			{
+				if (okToUnloadGraphics)
+				{
+					recursiveShutDownGraphic(graphic);
+					setGraphic(null);
+				}
+				if (widthIsComputed())
+					elementWidth = 0;
+				if (heightIsComputed())
+					elementHeight = 0;
+				changeGraphicStatus(InlineGraphicElementStatus.LOAD_PENDING);
+			}
+			return true;
+		}
+		
+		// searches through the graphic and stops any playing grpahics
+		private static function recursiveShutDownGraphic(graphic:DisplayObject):void
+		{
+			if (graphic is Loader)
+				Loader(graphic).unloadAndStop();
+			else if (graphic)
+			{
+				var container:DisplayObjectContainer = graphic as DisplayObjectContainer;
+				if (container)
+				{
+					for (var idx:int = 0; idx < container.numChildren; idx++)
+					{
+						recursiveShutDownGraphic(container.getChildAt(idx));
+					}
+				}
+
+				if (graphic is MovieClip)
+					MovieClip(graphic).stop();
+			}
+		}
+		
+		/** @private */
+		tlf_internal override function getEffectiveFontSize():Number
+		{
+			if (float != Float.NONE)
+				return 0;
+			var defaultLeading:Number = super.getEffectiveFontSize();
+			return Math.max(defaultLeading, elementHeight);
+		}
+		
+		/** Returns the actual ascent of the image. Used for computing baselines when they are ascent.  @private */
+		tlf_internal function getEffectiveAscent():Number
+		{
+			if (float != Float.NONE)
+				return 0;
+				
+			return elementHeight + GraphicElement(_blockElement).elementFormat.baselineShift;
+		}
+		
+		/** Returns the typographic ascent of the image (i.e. relative to the line's Roman baseline). @private */
+		tlf_internal function getTypographicAscent(textLine:TextLine):Number
+		{
+			if (float != Float.NONE)
+				return 0;
+				
+			var effectiveHeight:Number = elementHeight;
+			
+			var dominantBaselineString:String;
+			if(this._computedFormat.dominantBaseline != FormatValue.AUTO)
+			{
+				dominantBaselineString = this._computedFormat.dominantBaseline;
+			}
+			else
+			{
+				dominantBaselineString = this.getParagraph().getEffectiveDominantBaseline();
+			}
+			
+			var graphicElement:GraphicElement = GraphicElement(_blockElement);
+			var alignmentBaseline:String = (graphicElement.elementFormat.alignmentBaseline == flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE ? dominantBaselineString : graphicElement.elementFormat.alignmentBaseline);
+				
+			var top:Number=0;
+
+			// Calcluate relative to dominant baseline; remains 0 for ASCENT and IDEOGRAPHIC_TOP
+			if (dominantBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER)
+				top += effectiveHeight/2;
+			else if (dominantBaselineString == flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM || dominantBaselineString == flash.text.engine.TextBaseline.DESCENT || dominantBaselineString == flash.text.engine.TextBaseline.ROMAN)
+				top += effectiveHeight;
+				
+			// re-jig to be relative to the ROMAN baseline rather than whatever baseline is used for alignment
+			top += textLine.getBaselinePosition(flash.text.engine.TextBaseline.ROMAN) - textLine.getBaselinePosition(alignmentBaseline);
+			
+			// finally, account for baseline shift
+			top += graphicElement.elementFormat.baselineShift; 
+			
+			return top;
+		}
+		
+		/** @private */
+		 public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			if (endPos == -1)
+				endPos = textLength;
+				
+			var retFlow:InlineGraphicElement = super.shallowCopy(startPos, endPos) as InlineGraphicElement;
+			retFlow.source = source;
+			retFlow.width = width;
+			retFlow.height = height;
+			retFlow.float = float;
+			
+			return retFlow;
+		}
+
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+		
+		/** @private */
+		tlf_internal override function appendElementsForDelayedUpdate(tf:TextFlow):void
+		{ 
+			if (_graphicStatus == InlineGraphicElementStatus.LOAD_PENDING || _graphicStatus == InlineGraphicElementStatus.SIZE_PENDING || !tf.flowComposer || tf.flowComposer.numControllers == 0)
+				tf.appendOneElementForUpdate(this);
+		}
+		
+		/** @private */
+		tlf_internal override function calculateStrikeThrough(tLine:TextLine, blockProgression:String, metrics:FontMetrics):Number
+		{
+			if (!this.graphic || status != InlineGraphicElementStatus.READY)
+				return super.calculateStrikeThrough(tLine,blockProgression,metrics);
+				
+			var stOffset:Number = 0;
+		//	trace(spanBounds.y);
+		//	trace(this.graphic.getBounds(tLine));
+			var myBounds:Rectangle = this.graphic.getBounds(tLine);
+			
+			if(blockProgression != BlockProgression.RL)
+			{
+				stOffset = myBounds.y + this.elementHeight/2;
+			}
+			else
+			{
+				var line:TextFlowLine = tLine.userData as TextFlowLine;
+				var elemIdx:int = this.getAbsoluteStart() - line.absoluteStart;
+				if(tLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
+					stOffset = myBounds.x + this.elementHeight/2;
+				else
+					stOffset = myBounds.x + this.elementWidth/2;
+			}
+			
+			return blockProgression == BlockProgression.TB ? stOffset : -stOffset;
+		}
+		
+		/** @private */
+		tlf_internal override function calculateUnderlineOffset(stOffset:Number, blockProgression:String, metrics:FontMetrics, tLine:TextLine):Number
+		{
+			if (!this.graphic || status != InlineGraphicElementStatus.READY)
+				return super.calculateUnderlineOffset(stOffset,blockProgression,metrics,tLine);
+				
+			var ulOffset:Number = 0;
+			if(blockProgression == BlockProgression.TB)
+				ulOffset = this.graphic.getBounds(tLine).bottom;
+			else
+				ulOffset = this.graphic.getBounds(tLine).right;
+				
+			ulOffset += metrics.underlineOffset + (metrics.underlineThickness/2);
+			
+			var para:ParagraphElement = this.getParagraph();
+			var justRule:String = para.getEffectiveJustificationRule();
+			if(justRule == JustificationRule.EAST_ASIAN)
+				ulOffset += 1;
+		
+			return ulOffset;
+		}
+		// **************************************** 
+		// Begin debug support code
+		// ****************************************	
+		
+		/** @private */
+		CONFIG::debug public override function toString():String
+		{
+			return super.toString() + " " + source;
+		}
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			
+			var rslt:int = super.debugCheckFlowElement(depth,extraData+" url:"+source);
+
+			if (_blockElement)
+				rslt += assert(textLength == GraphicElement(_blockElement).rawText.length,"image is different than its textElement");
+			rslt += assert(this != getParagraph().getLastLeaf(),"last Leaf in paragraph cannot be image");
+
+			return rslt;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElementStatus.as b/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElementStatus.as
new file mode 100755
index 0000000..f8b7a3e
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/InlineGraphicElementStatus.as
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+    /** The InlineGraphicElementStatus class defines a set of constants for checking the value of
+     * <code>InlineGraphicElement.status</code>.
+     *
+     * @playerversion Flash 10
+     * @playerversion AIR 1.5
+     * @langversion 3.0
+     *
+     * @see InlineGraphicElement#status
+     */
+    public final class InlineGraphicElementStatus
+    {
+    	/** Graphic element is an URL that has not been loaded.  
+    	 *
+    	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+        public static const LOAD_PENDING:String = "loadPending";
+        
+        /** Load has been initiated (but not completed) on a graphic element that is a URL.  
+         *
+         * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+        public static const LOADING:String  	= "loading";
+        
+        /** 
+         * Graphic element with auto or percentage width/height has completed loading but has not been recomposed.  At the next 
+         * recompose the actual size of the graphic element is calculated. 
+         *
+         * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+        public static const SIZE_PENDING:String = "sizePending";
+        
+	/** Graphic is completely loaded and properly sized. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+        public static const READY:String = "ready";
+        
+        /** An error occurred during loading of a referenced graphic. 
+         *
+         * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+        public static const ERROR:String = "error";
+    }
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/LinkElement.as b/textLayout_core/src/flashx/textLayout/elements/LinkElement.as
new file mode 100755
index 0000000..c7e32b7
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/LinkElement.as
@@ -0,0 +1,885 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.display.DisplayObject;
+	import flash.display.Sprite;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IEventDispatcher;
+	import flash.events.MouseEvent;
+	import flash.net.*;
+	import flash.text.engine.GroupElement;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineMirrorRegion;
+	import flash.text.engine.TextLineValidity;
+	import flash.ui.Mouse;
+	import flash.ui.MouseCursor;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.EditingMode;
+	import flashx.textLayout.events.FlowElementMouseEvent;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+			
+	/** 
+	 * Dispatched when the mouse is pressed down over a link.
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.MOUSE_DOWN
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	[Event(name="mouseDown", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** 
+	 * Dispatched when the mouse is released over a link. 
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.MOUSE_UP
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+ 	 */
+	[Event(name="mouseUp", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	/** 
+	 * Dispatched when the mouse passes over the link. 
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.MOUSE_MOVE
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	[Event(name="mouseMove", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	/**
+	 * Dispatched when the mouse first enters the link. 
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.ROLL_OVER
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */			
+	[Event(name="rollOver", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	/** 
+	 * Dispatched when the mouse goes out of the link. 
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.ROLL_OUT
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	[Event(name="rollOut", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	/** 
+	 * Dispatched when the link is clicked. 
+	 * Clients may override how the link handles the event by handling it themselves, and calling preventDefault().
+	 * @eventType flashx.textLayout.events.FlowElementMouseEvent.CLICK
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */	
+	[Event(name="click", type="flashx.textLayout.events.FlowElementMouseEvent")]
+
+	/** The LinkElement class defines a link to a URI (Universal Resource Identifier), which is executed when the user clicks it.
+	 * The LinkElement class is a subclass of the SubParagraphGroupElement class and it can contain
+	 * one or more FlowElement objects, such as a SpanElement object that stores the link text. An empty
+	 * LinkElement, which does not contain a FlowElement object, is ignored.
+	 * <p>If you specify a target, it must be one of the following values:
+	 * <table class="innertable" width="100%">
+	 * <tr>
+	 *   <th>Target value</th> 
+	 *   <th>description</th>
+	 * </tr>
+	 * <tr>
+	 *   <td>_self</td>
+	 *   <td>Replaces the current HTML page. If it is in a frame or frameset, it will load within that frame. If it is
+	 *       the full browser, it opens to replace the page from which it came.</td>
+	 * </tr>
+	 * <tr>
+	 *   <td>_blank</td>
+	 *   <td>Opens a new browser name with no name.</td>
+	 * </tr>
+	 * <tr>
+	 *   <td>_parent</td>
+	 *   <td>Replaces the HTML page from which it came.</td>
+	 * </tr>
+	 * <tr>
+	 *   <td>_top</td>
+	 *   <td>Loads in the current browser, replacing anything within it, such as a frameset.</td>
+	 * </tr>
+	 * </table>
+	 * </p>
+	 *
+	 * @includeExample examples\LinkElementExample.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see LinkState
+	 * @see FlowElement#linkActiveFormat FlowElement.linkActiveFormat
+	 * @see FlowElement#linkHoverFormat FlowElement.linkHoverFormat
+	 * @see FlowElement#linkNormalFormat FlowElement.linkNormalFormat
+	 * @see TextFlow
+	 *
+	 */ 
+	 
+	public final class LinkElement extends SubParagraphGroupElement implements IEventDispatcher
+	{
+		private var _uriString:String;
+		private var _targetString:String;
+		private var _linkState:String;
+		private var _ignoreNextMouseOut:Boolean = false;
+		private var _mouseInLink:Boolean = false;
+		private var _isSelecting:Boolean = false;
+		private var _keyEventsAdded:Boolean = false;
+		private var eventDispatcher:EventDispatcher;
+		private var _mouseDownInLink:Boolean = false;
+
+		private static var _mouseInLinkElement:LinkElement;
+		
+		/** Constructor - creates a new LinkElement instance.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function LinkElement()
+		{
+			super();
+			
+           eventDispatcher = new EventDispatcher();
+            _linkState = LinkState.LINK;
+            _mouseDownInLink = false;
+            _isSelecting = false;
+        }
+        
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			super.createContentElement();
+			
+			var eventMirror:EventDispatcher = getEventMirror(SubParagraphGroupElement.INTERNAL_ATTACHED_LISTENERS);
+ 			eventMirror.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true);
+			eventMirror.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false, 0, true);
+			eventMirror.addEventListener(MouseEvent.MOUSE_OUT, mouseOutHandler, false, 0, true);
+			eventMirror.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler, false, 0, true);
+			eventMirror.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, 0, true);
+		}
+		
+		/** @private */
+        tlf_internal override function get precedence():uint { return 800; }
+        
+		/**
+		* @param type The type of event.
+		* @param listener The listener function that processes the event. This function must accept an event object 
+		* as its only parameter and must return nothing, as this example shows:
+		* <p><code>function(evt:Event):void</code></p>
+		* The function can have any name.
+		* @param useCapture Determines whether the listener works in the capture phase or the target 
+		* and bubbling phases. If <code>useCapture</code> is set to <code>true</code>, the  
+		* listener processes the event only during the capture phase and not in the target or 
+		* bubbling phase. If <code>useCapture</code> is <code>false</code>, the listener processes the event only
+		* during the target or bubbling phase. To listen for the event in all three phases, call 
+		* <code>addEventListener()</code> twice, once with <code>useCapture</code> set to <code>true</code>, 
+		* then again with <code>useCapture</code> set to <code>false</code>.
+		* @param priority The priority level of the event listener. Priorities are designated by a 32-bit integer. The higher the number, the higher the priority. All listeners with priority <em>n</em> are processed before listeners of priority <em>n-1</em>. If two or more listeners share the same priority, they are processed in the order in which they were added. The default priority is 0. 
+		* @param useWeakReference Determines whether the reference to the listener is strong or weak. A strong 
+		* reference (the default) prevents your listener from being garbage-collected. A weak 
+		* reference does not. <p>Class-level member functions are not subject to garbage 
+		* collection, so you can set <code>useWeakReference</code> to <code>true</code> for 
+		* class-level member functions without subjecting them to garbage collection. If you set
+		* <code>useWeakReference</code> to <code>true</code> for a listener that is a nested inner 
+		* function, the function will be garbge-collected and no longer persistent. If you create 
+		* references to the inner function (save it in another variable) then it is not 
+		* garbage-collected and stays persistent.</p>
+		*
+		* @copy flash.events.IEventDispatcher#addEventListener()
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/
+ 		 
+		public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false): void
+		{
+			eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
+		}
+
+		/**
+		 * @copy flash.events.IEventDispatcher#dispatchEvent()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function dispatchEvent(evt:Event):Boolean
+		{
+			return eventDispatcher.dispatchEvent(evt);
+		}
+		
+		/**
+		 * @copy flash.events.IEventDispatcher#hasEventListener()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function hasEventListener(type:String):Boolean
+		{
+			return eventDispatcher.hasEventListener(type);
+		}
+		
+		/**
+		 *
+		 * @param type The type of event.
+		 * @param listener The listener object to remove.
+		 * @param useCapture Specifies whether the listener was registered for the capture phase or the target and bubbling phases. If the listener was registered for both the capture phase and the target and bubbling phases, two calls to <code>removeEventListener()</code> are required to remove both: one call with <code>useCapture</code> set to <code>true</code>, and another call with <code>useCapture</code> set to <code>false</code>. 
+		 *
+		 * @copy flash.events.IEventDispatcher#removeEventListener().
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false): void
+		{
+			eventDispatcher.removeEventListener(type, listener, useCapture);
+		}
+
+		/**
+		 * @copy flash.events.IEventDispatcher#willTrigger()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function willTrigger(type:String):Boolean
+		{
+			return eventDispatcher.willTrigger(type);
+		}
+		// end of IEventDispatcher functions
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+		
+		
+		/**
+		 * The Uniform Resource Identifier (URI) associated with the LinkElement object.  The URI can be any URI 
+		 * supported by the <code>flash.net.navigateToURL()</code> method. This property maps
+		 * to the <code>request</code> parameter for that method.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see ../../../flash/net/package.html#navigateToURL() flash.net.navigateToURL()
+		 */
+		 
+		public function get href():String
+		{
+			return _uriString;
+		}
+		 
+		public function set href(newUriString:String):void
+		{
+			_uriString = newUriString;
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+		}
+
+		/**
+		 * The Target value associated with the LinkElement. Possible values are "_self", "_blank",
+		 * "_parent", and "_top". This value maps to the <code>window</code> parameter of the
+		 * <code>flash.net.navigateToURL()</code> method.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see ../../../flash/net/package.html#navigateToURL() flash.net.navigateToURL()
+		 */
+		 
+		public function get target():String
+		{
+			return _targetString;
+		}
+		public function set target(newTargetString:String):void
+		{
+			_targetString = newTargetString;
+			modelChanged(ModelChange.ELEMENT_MODIFIED,0,textLength);
+		}
+
+		/**
+		 * The current state of the link.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see LinkState
+		 */
+		 
+		public function get linkState():String
+		{ return _linkState; }
+		
+		/** @private */
+		 public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			if (endPos == -1)
+				endPos = textLength;
+				
+			var retFlow:LinkElement = super.shallowCopy(startPos, endPos) as LinkElement;
+			retFlow.href = href;
+			retFlow.target = target;
+			return retFlow;
+		}
+		
+		/** @private */
+		tlf_internal override function mergeToPreviousIfPossible():Boolean
+		{		
+			// in links the eventMirror exists.  TLF ignores that when merging.  The risk is that everything matches but the user has added a custom listener to the eventMirror.
+			var theParent:FlowGroupElement = parent;
+			if (theParent && !bindableElement)
+			{
+				var myidx:int = theParent.getChildIndex(this);
+				if (textLength == 0)
+				{
+					theParent.replaceChildren(myidx, myidx + 1, null);
+					return true;
+				}
+				
+				if (myidx != 0 && (attachedListenerStatus & SubParagraphGroupElement.CLIENT_ATTACHED_LISTENERS) == 0)
+				{
+					var sib:LinkElement = theParent.getChildAt(myidx-1) as LinkElement;
+					if (sib != null && (sib.attachedListenerStatus & SubParagraphGroupElement.CLIENT_ATTACHED_LISTENERS) == 0)
+					{
+						if ((this.href == sib.href) && (this.target == sib.target) && equalStylesForMerge(sib))
+						{
+							var curFlowElement:FlowElement = null;
+				   
+							if (numChildren > 0)
+							{
+								while (numChildren > 0)
+								{
+									curFlowElement = getChildAt(0);
+									replaceChildren(0, 1);
+									sib.replaceChildren(sib.numChildren, sib.numChildren, curFlowElement);
+								}
+							}
+							theParent.replaceChildren(myidx, myidx + 1, null);											
+							return true;
+						}
+					}
+				}
+			} 
+			return false;
+		}
+		
+		/** 
+		 * Specifies the name of the text format element of a LinkElement when the link is in the normal state.
+		 * @private
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		static tlf_internal const LINK_NORMAL_FORMAT_NAME:String = "linkNormalFormat";
+		
+		/** 
+		 * Specifies the name of the text format element of a LinkElement when the link is in the active state. 
+		 * @private
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		static tlf_internal const LINK_ACTIVE_FORMAT_NAME:String = "linkActiveFormat";
+		
+		/** Specifies the name of the text format element of a LinkElement when the cursor is hovering over the link. 
+		 * @private
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		static tlf_internal const LINK_HOVER_FORMAT_NAME:String  = "linkHoverFormat";
+		
+		private function computeLinkFormat(formatName:String):ITextLayoutFormat
+		{
+			var linkStyle:Object = getStyle(formatName);
+			if (linkStyle == null)
+			{
+				var tf:TextFlow = getTextFlow();
+				var formatStr:String = formatName.substr(1);
+				return tf == null ? null : tf.configuration["defaultL" + formatStr];
+			}
+			else if (linkStyle is ITextLayoutFormat)
+				return ITextLayoutFormat(linkStyle);
+		
+			// We need to convert the linkStyle object into a ITextLayoutFormat object		
+			var ca:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder;
+			var desc:Object = TextLayoutFormat.description;
+			for (var prop:String in desc)
+			{
+				if (linkStyle[prop] != undefined)
+					ca[prop] = linkStyle[prop];
+			}
+			return ca;
+		}
+		/** 
+		 * The state-dependent character attributes for the link.
+		 * @private
+		 */
+		
+		tlf_internal function get effectiveLinkElementTextLayoutFormat():ITextLayoutFormat
+		{	
+			var cf:ITextLayoutFormat;
+			if (_linkState == LinkState.ACTIVE)
+			{
+				cf = computeLinkFormat(LINK_ACTIVE_FORMAT_NAME);
+				if (cf)
+					return cf;
+			}
+			if (_linkState == LinkState.HOVER)
+			{
+				cf = computeLinkFormat(LINK_HOVER_FORMAT_NAME);
+				if (cf)
+					return cf;
+			}
+
+			return computeLinkFormat(LINK_NORMAL_FORMAT_NAME);
+		}
+		
+		/** @private */
+		tlf_internal override function get formatForCascade():ITextLayoutFormat
+		{
+			var superFormat:ITextLayoutFormat = format;
+			var effectiveFormat:ITextLayoutFormat = effectiveLinkElementTextLayoutFormat;
+			if (effectiveFormat || superFormat)
+			{
+				if (effectiveFormat && superFormat)
+				{
+					var resultingTextLayoutFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(effectiveFormat);
+					if (superFormat)
+						resultingTextLayoutFormat.concatInheritOnly(superFormat);
+					return resultingTextLayoutFormat;
+				}
+				return superFormat ? superFormat : effectiveFormat;
+			}
+			return null;
+		}
+		
+		/** @private */
+		CONFIG::debug tlf_internal override function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
+		{
+			
+			if (groupElement)
+			{
+				var groupTextLength:int = groupElement.rawText ? groupElement.rawText.length : null;
+				assert(groupTextLength == this.textLength, "LinkElement - gc = " + this.groupElement.rawText + " this.textLength = " + this.textLength);
+			}
+			
+			super.setParentAndRelativeStart(newParent,newStart);
+				
+		}
+		
+		private function redrawLink(ignoreNextMouseOut:Boolean=true):void
+		{
+			parent.formatChanged(true);
+			var tf:TextFlow = getTextFlow();
+			if (tf && tf.flowComposer)
+			{
+				tf.flowComposer.updateAllControllers();
+				if (_linkState != LinkState.HOVER) 
+					_ignoreNextMouseOut = ignoreNextMouseOut;
+			}
+		}
+		
+		private function setToState(linkState:String, ignoreNextMouseOut:Boolean=true):void
+		{
+			if (_linkState != linkState)
+			{
+				var oldCharAttrs:ITextLayoutFormat = effectiveLinkElementTextLayoutFormat;
+				_linkState = linkState;
+				var newCharAttrs:ITextLayoutFormat = effectiveLinkElementTextLayoutFormat;
+				if (!(TextLayoutFormat.isEqual(oldCharAttrs, newCharAttrs)))
+				{
+					redrawLink(ignoreNextMouseOut);
+				}		
+			}
+		}				
+		
+		private function setHandCursor(state:Boolean=true):void
+		{
+			var tf:TextFlow = getTextFlow();
+			if (tf != null && tf.flowComposer && tf.flowComposer.numControllers)
+			{
+				doToAllControllers(setContainerHandCursor);
+				if (state)
+					Mouse.cursor = MouseCursor.AUTO;
+				else
+				{
+					var wmode:String = tf.computedFormat.blockProgression;									
+					if (tf.interactionManager && (wmode != BlockProgression.RL))
+						Mouse.cursor = MouseCursor.IBEAM;
+					else
+						Mouse.cursor = MouseCursor.AUTO;
+				}
+			}
+			function setContainerHandCursor(controller:ContainerController):void
+			{
+				var container:Sprite = controller.container as Sprite;
+				if (container)
+				{
+					container.buttonMode = state;
+					container.useHandCursor = state;
+				}
+			}
+		
+		}
+		
+		private function handleEvent(event:FlowElementMouseEvent):Boolean
+		{
+			eventDispatcher.dispatchEvent(event);
+			if (event.isDefaultPrevented())
+				return true;
+			var textFlow:TextFlow = getTextFlow();
+			if (textFlow)
+			{
+				textFlow.dispatchEvent(event);
+				if (event.isDefaultPrevented())
+					return true;
+			}
+			return false;
+		}
+		
+		private function mouseDownHandler(evt:MouseEvent):void
+		{
+			CONFIG::debug { assert(getTextFlow() != null,"Invalid TextFlow"); }
+
+			if ((evt.ctrlKey) || (getTextFlow().interactionManager == null) || (getTextFlow().interactionManager.editingMode == EditingMode.READ_SELECT))
+			{									
+				if (_mouseInLink)
+				{
+					_mouseDownInLink = true;					
+					var event:FlowElementMouseEvent = new FlowElementMouseEvent("mouseDown", false, true, this, evt);
+					if (handleEvent(event)) return;
+					setHandCursor(true);
+					setToState(LinkState.ACTIVE, false);
+				}
+				evt.stopImmediatePropagation();								
+			}
+			else
+			{
+				setHandCursor(false);
+				setToState(LinkState.LINK);
+			}
+		}
+
+		private function mouseMoveHandler(evt:MouseEvent):void
+		{
+			CONFIG::debug { assert(getTextFlow() != null,"Invalid TextFlow"); }
+			if (_isSelecting) return;
+			if ((evt.ctrlKey) || (getTextFlow().interactionManager == null) || (getTextFlow().interactionManager.editingMode == EditingMode.READ_SELECT))
+			{
+				if (_mouseInLink)
+				{
+					var event:FlowElementMouseEvent = new FlowElementMouseEvent("mouseMove", false, true, this, evt);
+					if (handleEvent(event)) return;				
+					setHandCursor(true);
+					if (evt.buttonDown)
+					{
+						setToState(LinkState.ACTIVE, false);
+					}
+					else
+					{
+						setToState(LinkState.HOVER);
+					}
+				}
+			}
+			else
+			{
+				_mouseInLink = true;
+				setHandCursor(false);
+				setToState(LinkState.LINK);
+			}
+		}
+				
+		private function mouseOutHandler(evt:MouseEvent):void
+		{
+			if (!_ignoreNextMouseOut)
+			{
+				_mouseInLink = false;
+				LinkElement.removeLinkFromMouseInArray(this);							
+				_isSelecting = false;
+				_mouseDownInLink = false;
+				var event:FlowElementMouseEvent = new FlowElementMouseEvent(MouseEvent.ROLL_OUT, false, true, this, evt);
+				if (handleEvent(event)) return;				
+				setHandCursor(false);
+				setToState(LinkState.LINK);
+			}
+			_ignoreNextMouseOut = false;		
+		}
+		
+		private static function addLinkToMouseInArray(linkEl:LinkElement):void
+		{
+			CONFIG::debug { assert(_mouseInLinkElement == null, "Multiple links active"); }
+			_mouseInLinkElement = linkEl;
+			attachContainerEventHandlers(linkEl);
+		}
+		
+		private static function removeLinkFromMouseInArray(linkEl:LinkElement):void
+		{
+			_mouseInLinkElement = null;
+			detachContainerEventHandlers(linkEl);
+		}
+		
+		/** @private */
+		// This function is a workaround for Flash Player bug in Astro where mouseOut event is not sent from eventMirror if mouse
+		// has left the TextLine at the next sample point (i.e., mouse leaves TextLine rapidly).
+		private static function stageMouseMoveHandler(evt:MouseEvent):void
+		{
+			CONFIG::debug { assert(_mouseInLinkElement != null, "containerMouseMoveHandler shouldn't be active listener now"); }
+
+			 // Check to see if we are still in the link. We could be over an InlineGraphicElement, which could be part of the link.
+			 // In that case, we don't want to turn off the link.
+			var target:DisplayObject = evt.target as DisplayObject;
+			while (target && !(target is TextLine))
+				target = target.parent;
+			 
+			if (target)
+			{
+				var textLine:TextLine = target as TextLine;
+				if (textLine.validity != TextLineValidity.INVALID)
+				{
+					var mirrorRegions:Vector.<TextLineMirrorRegion> = textLine.mirrorRegions;
+					var found:Boolean = false;
+					if (mirrorRegions)
+					{
+						for (var i:int = 0; i < mirrorRegions.length; i++)
+						{
+							if (_mouseInLinkElement.groupElement == (mirrorRegions[i].element as GroupElement))
+								found = true;
+						}
+					}
+					if (!found)
+						target = null;
+				}
+			}
+			if (!target)		
+			{
+				LinkElement.setLinksToDefaultState(evt);
+				Mouse.cursor = MouseCursor.AUTO;
+			}
+		}
+		
+		/** @private */
+		private static function setLinksToDefaultState(evt:MouseEvent, linkEl:LinkElement = null):void
+		{
+			//FIXME - HBS.  Workaround for bug 1918187.  The problem is that the mouseOut event isn't
+			//always sent to the link when the mouse rolls over the link very quickly. So, we simulate
+			//the mouseOut when the next mouseMove over something other than a link is sent.  The problem
+			//is probably that the mouseOut is being sent before the LinkElement is fully constructed.
+			if (_mouseInLinkElement && (linkEl != _mouseInLinkElement))
+			{
+				var linkElement:LinkElement = _mouseInLinkElement;
+				removeLinkFromMouseInArray(linkElement);
+				linkElement._mouseInLink = false;
+				linkElement._isSelecting = false;
+				linkElement._mouseDownInLink = false;
+				var mouseMoveEvt:MouseEvent = new MouseEvent(MouseEvent.MOUSE_OUT, evt.bubbles, evt.cancelable, evt.localX, evt.localY, evt.relatedObject, evt.ctrlKey, evt.altKey, evt.shiftKey, evt.buttonDown, evt.delta); 
+				var event:FlowElementMouseEvent = new FlowElementMouseEvent(MouseEvent.ROLL_OUT, false, true, linkElement, mouseMoveEvt);
+				if (linkElement.handleEvent(event)) return;				
+				linkElement.setHandCursor(false);
+				linkElement.setToState(LinkState.LINK);
+				linkElement._ignoreNextMouseOut = false;
+			}
+		}
+		
+		private function doToAllControllers(functionToCall:Function):void
+		{
+			var textFlow:TextFlow = getTextFlow();
+			var flowComposer:IFlowComposer = textFlow.flowComposer;
+			var start:int = getAbsoluteStart();
+			var controllerIndex:int = flowComposer.findControllerIndexAtPosition(start);
+			var lastController:int = flowComposer.findControllerIndexAtPosition(start + textLength - 1);
+			while (controllerIndex <= lastController)
+			{
+				functionToCall(flowComposer.getControllerAt(controllerIndex));
+				controllerIndex++;
+			}
+		}
+		
+		private static function findRootForEventHandlers(linkElement:LinkElement):DisplayObject
+		{
+			var textFlow:TextFlow = linkElement.getTextFlow();
+			if (textFlow)
+			{
+				var flowComposer:IFlowComposer = textFlow.flowComposer;
+				if (flowComposer && flowComposer.numControllers != 0)
+					return flowComposer.getControllerAt(0).getContainerRoot();
+			}
+			return null;
+		}
+				
+		private static function attachContainerEventHandlers(linkElement:LinkElement):void
+		{
+			var root:DisplayObject = findRootForEventHandlers(linkElement);
+			if (root)
+				root.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false, 0, true);
+		}
+
+		private static function detachContainerEventHandlers(linkElement:LinkElement):void
+		{
+			var root:DisplayObject = findRootForEventHandlers(linkElement);
+			if (root)
+				root.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler);
+		}
+		
+		private function mouseOverHandler(evt:MouseEvent):void
+		{
+			if (_mouseInLink) return;
+			CONFIG::debug { assert(getTextFlow() != null,"Invalid TextFlow"); }									
+			if (evt.buttonDown) _isSelecting = true;
+			if (_isSelecting) return;
+			_mouseInLink = true;
+			LinkElement.setLinksToDefaultState(evt, this);			
+			LinkElement.addLinkToMouseInArray(this);
+			
+			if ((evt.ctrlKey) || (getTextFlow().interactionManager == null) || (getTextFlow().interactionManager.editingMode == EditingMode.READ_SELECT))
+			{
+				var event:FlowElementMouseEvent = new FlowElementMouseEvent(MouseEvent.ROLL_OVER, false, true, this, evt);
+				if (handleEvent(event)) return;				
+				setHandCursor(true);
+				if (evt.buttonDown)
+				{
+					setToState(LinkState.ACTIVE, false);
+				}
+				else
+				{
+					setToState(LinkState.HOVER, false);
+				}
+			}
+			else
+			{
+				setHandCursor(false);
+				setToState(LinkState.LINK);
+			}
+		}
+		
+		private function mouseUpHandler(evt:MouseEvent):void
+		{
+			CONFIG::debug { assert(getTextFlow() != null,"Invalid TextFlow"); }
+			if (_isSelecting) {_isSelecting = false; return; }												
+			if (_mouseInLink && ((evt.ctrlKey) || (getTextFlow().interactionManager == null) || (getTextFlow().interactionManager.editingMode == EditingMode.READ_SELECT)))
+			{
+				var event:FlowElementMouseEvent = new FlowElementMouseEvent("mouseUp", false, true, this, evt);
+				if (!handleEvent(event))				
+				{
+					setHandCursor(true);				
+					setToState(LinkState.HOVER);
+					evt.stopImmediatePropagation();
+				}
+				if (_mouseDownInLink) mouseClickHandler(evt);
+			} else {
+				setHandCursor(false);
+				setToState(LinkState.LINK);
+			}
+			_mouseDownInLink = false;
+		}
+		
+		private function mouseClickHandler(evt:MouseEvent):void
+		{
+			CONFIG::debug { assert(getTextFlow() != null,"Invalid TextFlow"); }
+			if (_isSelecting) return;
+			
+			if (((evt.ctrlKey) || (getTextFlow().interactionManager == null) || (getTextFlow().interactionManager.editingMode == EditingMode.READ_SELECT)))
+			{															
+				if (_mouseInLink)
+				{
+					var event:FlowElementMouseEvent = new FlowElementMouseEvent("click", false, true, this, evt);
+					if (handleEvent(event)) return;
+				
+					if (_uriString != null)
+					{
+						if ((_uriString.length > 6) && (_uriString.substr(0, 6) == "event:"))
+						{
+							event = new FlowElementMouseEvent(_uriString.substring(6, _uriString.length), false, true, this, evt);
+							handleEvent(event);
+						} else 
+						{
+		        			var u:URLRequest = new URLRequest(encodeURI(_uriString));
+		        			flash.net.navigateToURL(u, target);
+		   				}
+					}
+				}
+				evt.stopImmediatePropagation();		
+			}			
+		}
+		
+		/** @private */
+		tlf_internal override function acceptTextBefore():Boolean 
+		{ 
+			return false; 
+		}
+		
+		/** @private */
+		tlf_internal override function acceptTextAfter():Boolean
+		{
+			return false;
+		}
+		
+		/** @private */
+		/*public override function replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
+		{
+			var applyParams:Array = [beginChildIndex, endChildIndex];
+			super.replaceChildren.apply(this, applyParams.concat(rest));
+			
+			//make sure that all elements of Link recalculate their attributes when
+			//something is added to the link.
+			
+			var len:int = numChildren;
+			var i:int = 0;
+			var fl:FlowElement;
+			while (i < len)
+			{
+				fl = getChildAtIndex(i);
+				fl.formatChanged(true);
+				i++;
+			}
+		}*/
+					
+		/** @private This is done so that the TextContainerManager can discover LinkElements in a TextFlow. */
+		tlf_internal override function appendElementsForDelayedUpdate(tf:TextFlow):void
+		{ 
+			tf.appendOneElementForUpdate(this);
+			super.appendElementsForDelayedUpdate(tf);
+		}
+		
+		/** @private This API supports the inputmanager */
+		tlf_internal override function updateForMustUseComposer(textFlow:TextFlow):Boolean
+		{ return true; }
+
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/LinkState.as b/textLayout_core/src/flashx/textLayout/elements/LinkState.as
new file mode 100755
index 0000000..ee2c80d
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/LinkState.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 flashx.textLayout.elements
+{
+	/**
+	 *  The LinkState class defines a set of constants for the <code>linkState</code> property
+	 *  of the LinkElement class. 
+	 *
+	 * @includeExample examples\LinkStateExample.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 *  @see LinkElement#linkState
+	 */
+	 
+ 	public final class LinkState {
+ 	
+	/** 
+	 * Value for the normal, default link state. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+    	public static const LINK:String = "link";
+    
+	/** 
+	 * Value for the hover state, which occurs when you drag the mouse over a link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */ 
+	 
+    	public static const HOVER:String = "hover";
+    
+	/** 
+	 * Value for the active state, which occurs when you hold the mouse down over a link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+    	public static const ACTIVE:String = "active";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/OverflowPolicy.as b/textLayout_core/src/flashx/textLayout/elements/OverflowPolicy.as
new file mode 100755
index 0000000..e082185
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/OverflowPolicy.as
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	/**
+	 *  The OverflowPolicy class defines a set of constants for the <code>overflowPolicy</code> property
+	 *  of the IConfiguration class. This defines how the composer will treat lines at the end of the composition area.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+ 	public final class OverflowPolicy {
+ 	
+	/** 
+	 * Fit the line in the composition area if any part of the line fits.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+     public static const FIT_ANY:String = "fitAny";
+    
+	/*
+	 * Fit the line in the composition area if the area from the top to the baseline fits.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+ //    public static const FIT_BASELINE:String = "fitAny";
+    
+	/** 
+	 * Fit the line in the composition area if the area from the top to the baseline fits.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+     public static const FIT_DESCENDERS:String = "fitDescenders";
+    
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/ParagraphElement.as b/textLayout_core/src/flashx/textLayout/elements/ParagraphElement.as
new file mode 100755
index 0000000..661f583
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/ParagraphElement.as
@@ -0,0 +1,837 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements 
+{
+	import flash.display.Shape;
+	import flash.text.engine.ContentElement;
+	import flash.text.engine.EastAsianJustifier;
+	import flash.text.engine.GroupElement;
+	import flash.text.engine.LineJustification;
+	import flash.text.engine.SpaceJustifier;
+	import flash.text.engine.TabStop;
+	import flash.text.engine.TextBaseline;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.text.engine.TextRotation;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.JustificationRule;
+	import flashx.textLayout.formats.LeadingModel;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.formats.TabStopFormat;
+	import flashx.textLayout.formats.TextAlign;
+	import flashx.textLayout.formats.TextJustify;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.CharacterUtil;
+	import flashx.textLayout.utils.LocaleUtil;
+	
+	use namespace tlf_internal;
+
+	/** 
+	 * The ParagraphElement class represents a paragraph in the text flow hierarchy. Its parent
+	 * is a ParagraphFormattedElement, and its children can include spans (SpanElement), images 
+	 * (inLineGraphicElement), links (LinkElement) and TCY (Tatechuuyoko - ta-tae-chu-yo-ko) elements (TCYElement). The 
+	 * paragraph text is stored in one or more SpanElement objects, which define ranges of text that share the same attributes. 
+	 * A TCYElement object defines a small run of Japanese text that runs perpendicular to the line, as in a horizontal run of text in a 
+	 * vertical line. A TCYElement can also contain multiple spans.
+	 *
+	 * @includeExample examples\ParagraphElementExample.as -noswf
+	 * @includeExample examples\ParagraphElementExample2.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 * 
+	 * @see InlineGraphicElement
+	 * @see LinkElement
+	 * @see SpanElement
+	 * @see TCYElement
+	 * @see TextFlow
+	 */
+	 
+	public final class ParagraphElement extends ParagraphFormattedElement
+	{
+		private var _textBlock:TextBlock;
+		
+		/** Constructor - represents a paragraph in a text flow. 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function ParagraphElement()
+		{
+			super();
+		}
+		
+		/** @private */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			var retFlow:ParagraphElement = super.shallowCopy(startPos, endPos) as ParagraphElement;
+			if (_textBlock)
+				retFlow.createTextBlock();
+			return retFlow;
+		}
+		/** @private */
+		tlf_internal function createTextBlock():void
+		{
+			CONFIG::debug { assert(_textBlock == null,"createTextBlock called when there is already a textblock"); }
+			_textBlock = new TextBlock();
+			CONFIG::debug { Debugging.traceFTECall(_textBlock,null,"new TextBlock()"); }
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				child.createContentElement();
+			}
+			updateTextBlock();
+		}
+		
+		/** @private */
+		
+		tlf_internal function releaseTextBlock():void
+		{
+			if (!_textBlock)
+				return;
+				
+			// Preflight children to see if any are in use
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				if (!child.canReleaseContentElement())
+					return;
+			}
+
+			if (_textBlock.firstLine)	// A TextBlock may have no firstLine if it has previously been released.
+			{
+				for (var textLineTest:TextLine = _textBlock.firstLine; textLineTest != null; textLineTest = textLineTest.nextLine)
+				{	
+					if(textLineTest.numChildren != 0)
+					{	
+						//if the number of adornments added does not match the number of children on the textLine
+						//then a third party has added adornments.  Don't recycle the line or the adornment will be
+						//lost.
+						var tfl:TextFlowLine = textLineTest.userData as TextFlowLine;
+						if(tfl.adornCount != textLineTest.numChildren)
+							return;
+					}
+				}
+				
+				for (var textLine:TextLine = _textBlock.firstLine; textLine != null; textLine = textLine.nextLine)
+					TextFlowLine(textLine.userData).markReleased();
+				CONFIG::debug { Debugging.traceFTECall(null,_textBlock,"releaseLines",_textBlock.firstLine, _textBlock.lastLine); }				
+				_textBlock.releaseLines(_textBlock.firstLine, _textBlock.lastLine);	
+			}	
+
+			_textBlock.content = null;
+			for (i = 0; i < numChildren; i++)
+			{
+				child = getChildAt(i);
+				child.releaseContentElement();
+			}
+			_textBlock = null;
+			
+		}
+		
+		/** TextBlock where the text of the paragraph is kept. @private */
+		tlf_internal function getTextBlock():TextBlock
+		{ 
+			if (!_textBlock)
+				createTextBlock();
+			return _textBlock; 
+		}
+		
+		/** @private */
+		tlf_internal function releaseLineCreationData():void
+		{
+			CONFIG::debug { assert(Configuration.playerEnablesArgoFeatures,"bad call to releaseLineCreationData"); }
+			if (_textBlock)
+				_textBlock["releaseLineCreationData"]();
+		}
+		
+		/** @private */
+		tlf_internal override function createContentAsGroup():GroupElement
+		{ 			
+			var group:GroupElement = _textBlock.content as GroupElement;
+			if (!group)
+			{
+				var originalContent:ContentElement = _textBlock.content;
+				
+				group = new GroupElement();
+				CONFIG::debug { Debugging.traceFTECall(group,null,"new GroupElement()"); }
+				_textBlock.content = group;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",group); }
+
+				if (originalContent)
+				{
+					var gc:Vector.<ContentElement> = new Vector.<ContentElement>();
+					CONFIG::debug { Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>()") }
+					gc.push(originalContent);
+					CONFIG::debug { Debugging.traceFTECall(null,gc,"push",originalContent); }
+					group.replaceElements(0,0,gc);
+					CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",0,0,gc); }
+				}
+				
+				// Now we've got to force damage the entire paragraph, because we restructured it in FTE.
+				if (_textBlock.firstLine && textLength)
+				{
+					var textFlow:TextFlow = getTextFlow();
+					if (textFlow)
+						textFlow.damage(getAbsoluteStart(), textLength, TextLineValidity.INVALID, false);
+				}
+			}
+			return group;
+ 		}
+ 		
+ 		/** @private */
+		tlf_internal override function removeBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			if (numChildren == 1)
+			{
+				if (block is GroupElement)
+				{
+					// see insertBlockElement
+					CONFIG::debug { assert(_textBlock.content != block,"removeBlockElement: bad call to removeBlockElement"); }
+					CONFIG::debug { assert(_textBlock.content is GroupElement,"removeBlockElement: bad content"); }
+					CONFIG::debug { assert(GroupElement(_textBlock.content).elementCount == 1,"removeBlockElement: bad element count"); }
+					CONFIG::debug { assert(GroupElement(_textBlock.content).getElementAt(0) == block,"removeBlockElement: bad group content"); }
+					GroupElement(_textBlock.content).replaceElements(0,1,null);
+					CONFIG::debug { Debugging.traceFTECall(null,_textBlock.content,"replaceElements",0,1,null); }
+				}
+				_textBlock.content = null;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",null); }
+			}
+			else
+			{
+				var idx:int = this.getChildIndex(child);
+				var group:GroupElement = GroupElement(_textBlock.content);
+				CONFIG::debug { assert(group.elementCount == numChildren,"Mismatched group and elementCount"); }
+				group.replaceElements(idx,idx+1,null);
+				CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",idx,idx+1,null); }
+				if (numChildren == 2)	// its going to be one so ungroup
+				{
+					// ungroup - need to take it out first as inlinelements can only have one parent
+					var elem:ContentElement = group.getElementAt(0);
+					CONFIG::debug { Debugging.traceFTECall(elem,group,"getElementAt",0); }
+					if (!(elem is GroupElement))
+					{
+						group.replaceElements(0,1,null);
+						CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",0,1,null); }
+						_textBlock.content = elem;
+						CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",elem); }
+					}
+				}
+			}
+		}
+		
+		
+		/** @private */
+		tlf_internal override function hasBlockElement():Boolean
+		{
+			return _textBlock != null;
+		}
+		
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			createTextBlock();
+		}
+		
+		/** @private */
+		tlf_internal override function insertBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			if (_textBlock == null)
+			{
+				child.releaseContentElement();
+				createTextBlock();	// does the whole tree
+				return;
+			}
+			var gc:Vector.<ContentElement>;	// scratch var
+			var group:GroupElement;			// scratch
+			if (numChildren == 1)
+			{
+				if (block is GroupElement)
+				{
+					// this case forces the Group to be in a Group so that following FlowLeafElements aren't in a SubParagraphGroupElement's group
+					gc = new Vector.<ContentElement>();
+					CONFIG::debug { Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>()") }
+					gc.push(block);
+					CONFIG::debug { Debugging.traceFTECall(null,gc,"push",block); }
+					group = new GroupElement(gc);
+					CONFIG::debug { Debugging.traceFTECall(group,null,"new GroupElement",gc); }
+					_textBlock.content = group;
+					CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",group); }
+				}
+				else
+				{
+					_textBlock.content = block;
+					CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"content",block);  }
+				}
+			}
+			else
+			{
+				group = createContentAsGroup();
+				var idx:int = this.getChildIndex(child);
+				gc = new Vector.<ContentElement>();
+				CONFIG::debug { Debugging.traceFTECall(gc,null,"new Vector.<ContentElement>") }
+				gc.push(block);
+				CONFIG::debug { Debugging.traceFTECall(null,gc,"push",block); }
+				group.replaceElements(idx,idx,gc);
+				CONFIG::debug { Debugging.traceFTECall(null,group,"replaceElements",idx,idx,gc); }
+			}
+		}
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+
+		/** @private */
+		public override function replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
+		{
+			// are we replacing the last element?
+			var oldLastLeaf:FlowLeafElement = getLastLeaf();
+			
+			CONFIG::debug 
+			{ 
+				if (oldLastLeaf && (oldLastLeaf is SpanElement))
+					SpanElement(oldLastLeaf).verifyParagraphTerminator();
+
+			}
+			var applyParams:Array;
+			
+			// makes a measurable difference - rest.length zero and one are the common cases
+			if (rest.length == 1)
+				applyParams = [beginChildIndex, endChildIndex, rest[0]];
+			else
+			{
+				applyParams = [beginChildIndex, endChildIndex];
+				if (rest.length != 0)
+					applyParams = applyParams.concat.apply(applyParams, rest);
+			}
+			super.replaceChildren.apply(this, applyParams);
+			
+			ensureTerminatorAfterReplace(oldLastLeaf);
+		}
+		/** @private */
+		tlf_internal function ensureTerminatorAfterReplace(oldLastLeaf:FlowLeafElement):void
+		{
+			var newLastLeaf:FlowLeafElement = getLastLeaf();
+			if (oldLastLeaf != newLastLeaf)
+			{
+				if (oldLastLeaf && oldLastLeaf is SpanElement)
+					oldLastLeaf.removeParaTerminator();
+				if (newLastLeaf)
+				{
+					if (newLastLeaf is SpanElement)
+						newLastLeaf.addParaTerminator();
+					else
+					{
+						var s:SpanElement = new SpanElement();
+						super.replaceChildren(numChildren,numChildren,s);
+						s.format = newLastLeaf.format;
+						s.addParaTerminator();
+					}
+				}
+			}
+		}
+
+		[RichTextContent]
+		/** @private NOTE: all FlowElement implementers and overrides of mxmlChildren must specify [RichTextContent] metadata */
+		public override function set mxmlChildren(array:Array):void
+		{
+			// remove all existing children
+			replaceChildren(0,numChildren);
+			
+			for each (var child:Object in array)
+			{
+				if (child is FlowElement)
+				{
+					if ((child is SpanElement) || (child is SubParagraphGroupElement))
+						child.bindableElement = true;
+					
+					// Note: calling super.replaceChildren because we don't want to transfer para terminator each time
+					super.replaceChildren(numChildren, numChildren, child as FlowElement); 
+				}
+				else if (child is String)
+				{
+					var s:SpanElement = new SpanElement();
+					s.text = String(child);
+					s.bindableElement = true;
+					
+					// Note: calling super.replaceChildren because we don't want to transfer para terminator each time
+					super.replaceChildren(numChildren, numChildren, s);
+				}
+				else if (child != null)
+					throw new TypeError(GlobalSettings.resourceStringFunction("badMXMLChildrenArgument",[ getQualifiedClassName(child) ]));
+			}
+			
+			// Now ensure para terminator
+			ensureTerminatorAfterReplace(null);
+		}
+		
+		/** @private
+ 		 */
+		public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+		{
+			// Optimization for getting text of the entire paragraph
+			if (relativeStart == 0 && (relativeEnd == -1 || relativeEnd >= textLength-1) && _textBlock)
+			{
+				if (_textBlock.content)
+				{
+					var text:String = _textBlock.content.rawText;
+					return text.substring(0, text.length - 1);
+				}
+				return "";		// content is null
+			}
+			return super.getText(relativeStart, relativeEnd, paragraphSeparator);
+		}
+		
+		/** Returns the paragraph that follows this one, or null if there are no more paragraphs. 
+		 *
+		 * @return the next paragraph or null if there are no more paragraphs.
+		 *
+		 * @includeExample examples\ParagraphElement_getNextParagraph.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see #getPreviousParagraph()
+	 	 */
+		public function getNextParagraph():ParagraphElement
+		{
+			var nextLeaf:FlowLeafElement = getLastLeaf().getNextLeaf();
+			return nextLeaf ? nextLeaf.getParagraph() : null;
+		}
+	
+		/** Returns the paragraph that precedes this one, or null, if this paragraph is the first one 
+		 * in the TextFlow. 
+		 *
+		 * @includeExample examples\ParagraphElement_getPreviousParagraph.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #getNextParagraph()
+	 	 */
+		public function getPreviousParagraph():ParagraphElement
+		{
+			var previousLeaf:FlowLeafElement = getFirstLeaf().getPreviousLeaf();
+			return previousLeaf ? previousLeaf.getParagraph() : null;
+		}
+	
+		/** 
+		 * Scans backward from the supplied position to find the location
+		 * in the text of the previous atom and returns the index. The term atom refers to 
+		 * both graphic elements and characters (including groups of combining characters), the 
+		 * indivisible entities that make up a text line.
+		 * 
+		 * @param relativePosition  position in the text to start from, counting from 0
+		 * @return index in the text of the previous cluster
+		 *
+		 * @includeExample examples\ParagraphElement_findPreviousAtomBoundary.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flash.text.engine.TextLine
+		 */
+		 
+		public function findPreviousAtomBoundary(relativePosition:int):int
+		{
+			return getTextBlock().findPreviousAtomBoundary(relativePosition);
+		}
+
+		/** 
+		 * Scans ahead from the supplied position to find the location
+		 * in the text of the next atom and returns the index. The term atom refers to 
+		 * both graphic elements and characters (including groups of combining characters), the 
+		 * indivisible entities that make up a text line.
+		 * 
+		 * @param relativePosition  position in the text to start from, counting from 0
+		 * @return index in the text of the following atom
+		 *
+		 * @includeExample examples\ParagraphElement_findNextAtomBoundary.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flash.text.engine.TextLine
+		 */
+		 
+		public function findNextAtomBoundary(relativePosition:int):int
+		{
+			return getTextBlock().findNextAtomBoundary(relativePosition);
+		}
+		
+		/** @private */
+		public override function getCharAtPosition(relativePosition:int):String
+		{
+			return getTextBlock().content.rawText.charAt(relativePosition);
+		} 
+
+		/** 
+		 * Returns the index of the previous word boundary in the text.
+		 * 
+		 * <p>Scans backward from the supplied position to find the previous position
+		 * in the text that starts or ends a word. </p>
+		 * 
+		 * @param relativePosition  position in the text to start from, counting from 0
+		 * @return index in the text of the previous word boundary
+		 *
+		 * @includeExample examples\ParagraphElement_findPreviousWordBoundary.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function findPreviousWordBoundary(relativePosition:int):int
+		{	
+			if (relativePosition == 0)
+				return 0;
+			var prevCharCode:int = getCharCodeAtPosition(relativePosition - 1);
+			if (CharacterUtil.isWhitespace(prevCharCode))
+			{				
+				while (CharacterUtil.isWhitespace(prevCharCode) && ((relativePosition - 1) > 0))
+				{
+					relativePosition--;
+					prevCharCode = getCharCodeAtPosition(relativePosition - 1);
+				}
+				return relativePosition;
+			}
+			return getTextBlock().findPreviousWordBoundary(relativePosition);
+		}
+
+		/** 
+		 * Returns the index of the next word boundary in the text.
+		 * 
+		 * <p>Scans ahead from the supplied position to find the next position
+		 * in the text that starts or ends a word. </p>
+		 * 
+		 * @param relativePosition  position in the text to start from, counting from 0
+		 * @return  index in the text of the next word boundary
+		 * 
+		 * @includeExample examples\ParagraphElement_findNextWordBoundary.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		 
+		public function findNextWordBoundary(relativePosition:int):int
+		{	
+			if (relativePosition == textLength) 
+				return textLength;
+			var curCharCode:int = getCharCodeAtPosition(relativePosition);
+			if (CharacterUtil.isWhitespace(curCharCode))
+			{
+				while (CharacterUtil.isWhitespace(curCharCode) && relativePosition < (textLength - 1))
+				{
+					relativePosition++;
+					curCharCode = getCharCodeAtPosition(relativePosition);
+				}
+				return relativePosition;
+			}
+			return getTextBlock().findNextWordBoundary(relativePosition);
+		}
+		
+		private static var _defaultTabStops:Vector.<TabStop>;
+		private const defaultTabWidth:int = 48;		// matches default tabs setting in Argo
+		private const defaultTabCount:int = 20;
+		
+		private function initializeDefaultTabStops():void
+		{
+			var lastTabPos:int = defaultTabWidth * defaultTabCount;
+			_defaultTabStops = new Vector.<TabStop>(defaultTabCount, true);
+			for (var i:int = 0; i < defaultTabCount; ++i)
+				_defaultTabStops[i] = new TabStop(TextAlign.START, defaultTabWidth * i);
+		}
+		
+		private function updateTextBlock():void
+		{
+			// find the ancestor with a container and use its format for various settings
+			var containerElement:ContainerFormattedElement = getAncestorWithContainer();
+			if (!containerElement)
+				return;
+				
+			var containerElementFormat:ITextLayoutFormat = containerElement ? containerElement.computedFormat : TextLayoutFormat.defaultFormat;
+			
+			var lineJust:String;
+			if (computedFormat.textAlign == TextAlign.JUSTIFY)
+			{
+				lineJust = (_computedFormat.textAlignLast == TextAlign.JUSTIFY) ?
+					LineJustification.ALL_INCLUDING_LAST :
+					LineJustification.ALL_BUT_LAST;
+					
+				// We don't allow explicit line breaks and justification together because it results in very strange (invisible) lines
+				if (containerElementFormat.lineBreak == LineBreak.EXPLICIT)
+					lineJust = LineJustification.UNJUSTIFIED;
+			}
+			else
+				lineJust = LineJustification.UNJUSTIFIED;
+		
+			
+			var makeJustRuleStyle:String = this.getEffectiveJustificationStyle();
+			
+			var justRule:String = this.getEffectiveJustificationRule();
+				
+			// set the justifier in the TextBlock
+			if (justRule == JustificationRule.SPACE)
+			{
+				var spaceJustifier:SpaceJustifier = new SpaceJustifier(_computedFormat.locale,lineJust,false);
+				spaceJustifier.letterSpacing = _computedFormat.textJustify == TextJustify.DISTRIBUTE ? true : false;
+				CONFIG::debug { Debugging.traceFTECall(spaceJustifier,null,"new SpaceJustifier",_computedFormat.locale,lineJust,false); }
+				_textBlock.textJustifier = spaceJustifier;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"textJustifier",spaceJustifier); }
+				_textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+			}
+			else
+			{
+				var eastAsianJustifier:EastAsianJustifier = new EastAsianJustifier(_computedFormat.locale,lineJust, makeJustRuleStyle);
+				CONFIG::debug { Debugging.traceFTECall(eastAsianJustifier,null,"new EastAsianJustifier",_computedFormat.locale,lineJust,makeJustRuleStyle); }
+				_textBlock.textJustifier = eastAsianJustifier;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"textJustifier",eastAsianJustifier);  }
+				_textBlock.baselineZero = getLeadingBasis(this.getEffectiveLeadingModel());
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"baselineZero",_textBlock.baselineZero);  }
+			}
+			
+			_textBlock.bidiLevel = _computedFormat.direction == Direction.LTR ? 0 : 1;
+			CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"bidiLevel",_textBlock.bidiLevel);  }
+
+			_textBlock.lineRotation = containerElementFormat.blockProgression == BlockProgression.RL ? TextRotation.ROTATE_90 : TextRotation.ROTATE_0;
+			CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"lineRotation",_textBlock.lineRotation);  }
+			
+			if (_computedFormat.tabStops && _computedFormat.tabStops.length != 0)
+			{
+				//create a vector of TabStops and assign it to tabStops in _textBlock
+				var tabStops:Vector.<TabStop> = new Vector.<TabStop>();
+				CONFIG::debug { Debugging.traceFTECall(tabStops,null,"new Vector.<TabStop>()"); }
+				for each(var tsa:TabStopFormat in _computedFormat.tabStops)
+				{
+					var token:String = tsa.decimalAlignmentToken==null ? "" : tsa.decimalAlignmentToken;
+					var tabStop:TabStop = new TabStop(tsa.alignment,Number(tsa.position),token);
+					// this next line when uncommented works around bug 1912782
+					if (tsa.decimalAlignmentToken != null) var garbage:String = "x" + tabStop.decimalAlignmentToken;
+					CONFIG::debug { Debugging.traceFTECall(tabStop,null,"new TabStop",tabStop.alignment,tabStop.position,tabStop.decimalAlignmentToken); }
+					tabStops.push(tabStop);
+					CONFIG::debug { Debugging.traceFTECall(null,tabStops,"push",tabStop); }
+				}
+				_textBlock.tabStops = tabStops;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",tabStops);  }
+			} 
+			else if (GlobalSettings.enableDefaultTabStops && !Configuration.playerEnablesArgoFeatures)
+			{
+				// 	Player versions prior to 10.1 do not set up any default tabStops. As a workaround, if enableDefaultTabs
+				//	is true, TLF will set up default tabStops in the case where there are no tabs defined. 
+				if (_defaultTabStops == null)
+					initializeDefaultTabStops();
+				_textBlock.tabStops = _defaultTabStops;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",_defaultTabStops);  }
+			}
+			else
+			{
+				_textBlock.tabStops = null;
+				CONFIG::debug { Debugging.traceFTEAssign(_textBlock,"tabStops",null);  }
+			}		 
+		}
+		
+		/** @private */
+		public override function get computedFormat():ITextLayoutFormat
+		{
+			if (!_computedFormat)
+			{
+				super.computedFormat;
+				if (_textBlock)
+					updateTextBlock();
+			}
+			return _computedFormat;
+		}
+
+		/** @private */
+		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
+		{
+			return elem is FlowLeafElement || elem is SubParagraphGroupElement;
+		}
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			var idx:int = findChildIndexAtPosition(normalizeStart);
+			if (idx != -1 && idx < numChildren)
+			{
+				var child:FlowElement = getChildAt(idx);
+				normalizeStart = normalizeStart-child.parentRelativeStart;
+				
+				CONFIG::debug { assert(normalizeStart >= 0, "bad normalizeStart in normalizeRange"); }
+				for (;;)
+				{
+					// watch out for changes in the length of the child
+					var origChildEnd:int = child.parentRelativeStart+child.textLength;
+					child.normalizeRange(normalizeStart,normalizeEnd-child.parentRelativeStart);
+					var newChildEnd:int = child.parentRelativeStart+child.textLength;
+					normalizeEnd += newChildEnd-origChildEnd;	// adjust
+					
+					// no zero length children
+					if (child.textLength == 0 && !child.bindableElement)
+						replaceChildren(idx,idx+1);
+					else if (child.mergeToPreviousIfPossible())
+					{
+						var prevElement:FlowElement = this.getChildAt(idx-1);
+						// possibly optimize the start to the length of prevelement before the merge
+						prevElement.normalizeRange(0,prevElement.textLength);
+					}
+					else
+						idx++;
+
+					if (idx == numChildren)
+					{
+						// check if last child is an empty SubPargraphBlock and remove it
+						if (idx != 0)
+						{
+							var lastChild:FlowElement = this.getChildAt(idx-1);
+							if (lastChild is SubParagraphGroupElement && lastChild.textLength == 1 && !lastChild.bindableElement)
+								replaceChildren(idx-1,idx);
+						}
+						break;
+					}
+					
+					// next child
+					child = getChildAt(idx);
+					
+					if (child.parentRelativeStart > normalizeEnd)
+						break;
+						
+					normalizeStart = 0;		// for the next child	
+				}
+			}
+			
+			// empty paragraphs not allowed after normalize
+			if (numChildren == 0 || textLength == 0)
+			{
+				var s:SpanElement = new SpanElement();
+				replaceChildren(0,0,s);
+				s.normalizeRange(0,s.textLength);
+			}
+		}
+		
+		/** @private */
+		tlf_internal function getEffectiveLeadingModel():String
+		{
+			return computedFormat.leadingModel == LeadingModel.AUTO ? LocaleUtil.leadingModel(computedFormat.locale) : computedFormat.leadingModel;
+		}
+		
+		/** @private */
+		tlf_internal function getEffectiveDominantBaseline():String
+		{
+			return computedFormat.dominantBaseline == FormatValue.AUTO ? LocaleUtil.dominantBaseline(computedFormat.locale) : computedFormat.dominantBaseline;
+		}
+		
+		/** @private */
+		tlf_internal function getEffectiveJustificationRule():String
+		{
+			return computedFormat.justificationRule == FormatValue.AUTO ? LocaleUtil.justificationRule(computedFormat.locale) : computedFormat.justificationRule;
+		}
+		
+		/** @private */
+		tlf_internal function getEffectiveJustificationStyle():String
+		{
+			return computedFormat.justificationStyle == FormatValue.AUTO ? LocaleUtil.justificationStyle(computedFormat.locale) : computedFormat.justificationStyle;
+		}
+		
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(_textBlock)+" "+extraData);
+			
+			// now check the character count and then the last character 
+			
+			if (_textBlock)
+			{
+				var contentLength:int = _textBlock.content && _textBlock.content.rawText ? _textBlock.content.rawText.length : 0;
+				rslt += assert(contentLength == textLength,"Bad paragraph length mode:"+textLength.toString()+" _textBlock:" + contentLength.toString());
+
+				var groupElement:GroupElement = _textBlock.content as GroupElement;
+				if (groupElement)
+					assert(groupElement.elementCount == numChildren,"Mismatched group and elementCount"); 
+				else if (_textBlock.content)
+					assert(1 == numChildren,"Mismatched group and elementCount"); 
+				else 
+					assert(0 == numChildren,"Mismatched group and elementCount"); 
+			}
+			rslt += assert(numChildren == 0 || textLength > 0,"Para must have at least one text char");
+			return rslt;
+		}
+		
+		/** @private */
+		tlf_internal static function getLeadingBasis (leadingModel:String):String
+		{
+			switch (leadingModel)
+			{
+				default:
+					CONFIG::debug { assert(false,"Unsupported parameter to ParagraphElement.getLeadingBasis"); } // In particular, AUTO is not supported by this method. Must be mapped to one of the above 
+				case LeadingModel.ASCENT_DESCENT_UP:
+				case LeadingModel.APPROXIMATE_TEXT_FIELD:
+				case LeadingModel.ROMAN_UP:
+					return flash.text.engine.TextBaseline.ROMAN;
+				case LeadingModel.IDEOGRAPHIC_TOP_UP:
+				case LeadingModel.IDEOGRAPHIC_TOP_DOWN:
+					return flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP;
+				case LeadingModel.IDEOGRAPHIC_CENTER_UP:
+				case LeadingModel.IDEOGRAPHIC_CENTER_DOWN:
+					return flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER;
+			}
+		}
+		
+		/** @private */
+		tlf_internal static function useUpLeadingDirection (leadingModel:String):Boolean
+		{
+			switch (leadingModel)
+			{
+				default:
+					CONFIG::debug { assert(false,"Unsupported parameter to ParagraphElement.useUpLeadingDirection"); } // In particular, AUTO is not supported by this method. Must be mapped to one of the above 
+				case LeadingModel.ASCENT_DESCENT_UP:
+				case LeadingModel.APPROXIMATE_TEXT_FIELD:
+				case LeadingModel.ROMAN_UP:
+				case LeadingModel.IDEOGRAPHIC_TOP_UP:
+				case LeadingModel.IDEOGRAPHIC_CENTER_UP:
+					return true;
+				case LeadingModel.IDEOGRAPHIC_TOP_DOWN:
+				case LeadingModel.IDEOGRAPHIC_CENTER_DOWN:
+					return false;
+			}
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/ParagraphFormattedElement.as b/textLayout_core/src/flashx/textLayout/elements/ParagraphFormattedElement.as
new file mode 100755
index 0000000..0c1b3e5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/ParagraphFormattedElement.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.property.Property;	
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** The ParagraphFormattedElement class is an abstract base class for FlowElement classes that have paragraph properties.
+	*
+	* <p>You cannot create a ParagraphFormattedElement object directly. Invoking <code>new ParagraphFormattedElement()</code> 
+	* throws an error exception.</p> 
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*
+	* @see ContainerFormattedElement
+	* @see ParagraphElement
+	* 
+	*/
+	public class ParagraphFormattedElement extends FlowGroupElement
+	{
+		/** @private TODO: DELETE THIS CLASS */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			return super.shallowCopy(startPos, endPos) as ParagraphFormattedElement;
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/SpanElement.as b/textLayout_core/src/flashx/textLayout/elements/SpanElement.as
new file mode 100755
index 0000000..ebff88a
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/SpanElement.as
@@ -0,0 +1,596 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.text.engine.GroupElement;
+	import flash.text.engine.TextElement;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.WhiteSpaceCollapse;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.CharacterUtil;
+	
+	use namespace tlf_internal;
+			
+	[DefaultProperty("mxmlChildren")]
+	
+	/** 
+	* The SpanElement class represents a run of text that has a single set of formatting attributes applied. SpanElement 
+	* objects contain the text in a paragraph. A simple paragraph (ParagraphElement) includes one or more SpanElement objects. 
+	*
+	* <p>A ParagraphElement will have a single SpanElement object if all the text in the paragraph shares the same set of 
+	* attributes. It has multiple SpanElement objects if the text in the paragraph has multiple formats.</p>
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*
+	* @includeExample examples/SpanElementExample.as -noswf
+	*
+	* @see FlowElement
+	* @see ParagraphElement
+	* @see TextFlow
+     	*/
+     	
+	public class SpanElement extends FlowLeafElement
+	{	
+		/** @private */
+		tlf_internal static const kParagraphTerminator:String = '\u2029';
+		
+		/** Constructor - creates a SpanElement object to hold a run of text in a paragraph.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function SpanElement():void
+		{
+			super();
+		}
+		
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			if (_blockElement)
+				return;
+				
+			_blockElement = new TextElement(null,null);			
+			CONFIG::debug { Debugging.traceFTECall(_blockElement,null,"new TextElement",null,null); }
+			TextElement(_blockElement).replaceText(0, 0, _text);
+			CONFIG::debug { Debugging.traceFTECall(null,_blockElement,"replaceText",0,0,_text); }
+			_text = null;
+			super.createContentElement();
+		}
+		/** @private */
+		override tlf_internal function releaseContentElement():void
+		{
+			if (_blockElement == null || !canReleaseContentElement())
+				return;
+			
+			CONFIG::debug { assert(_text == null, "_text already has content -- out of date?");	}
+			_text = _blockElement.rawText;
+			super.releaseContentElement();
+		}
+		
+		/** @private */
+		private function getTextElement():TextElement
+		{ return TextElement(_blockElement); }
+		
+		/** @private */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			if (endPos == -1)
+				endPos = textLength;
+				
+			// Note to callers: If you are calling this function outside a try/catch, do ensure that the 
+			// state of the model is coherent before the call.
+			var retFlow:SpanElement = super.shallowCopy(startPos, endPos) as SpanElement;
+						
+			var startSpan:int = 0;
+			var endSpan:int = startSpan + textLength;
+			
+			var leafElStartPos:int = startSpan >= startPos ? startSpan : startPos;
+			var leafElEndPos:int =  endSpan < endPos ? endSpan : endPos;
+			if (leafElEndPos == textLength && hasParagraphTerminator)
+				--leafElEndPos;
+				
+			if (leafElStartPos > leafElEndPos)
+				throw RangeError(GlobalSettings.resourceStringFunction("badShallowCopyRange"));
+			
+			var spanText:String = _blockElement ? _blockElement.rawText : _text;
+			if (((leafElStartPos != endSpan) && CharacterUtil.isLowSurrogate(spanText.charCodeAt(leafElStartPos))) ||
+				((leafElEndPos != 0) && CharacterUtil.isHighSurrogate(spanText.charCodeAt(leafElEndPos-1))))
+					throw RangeError(GlobalSettings.resourceStringFunction("badSurrogatePairCopy"));
+			
+			retFlow.replaceText(0, retFlow.textLength,  String(spanText).substring(leafElStartPos, leafElEndPos));
+			
+			return retFlow;
+		}	
+	
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+
+		/** @private */
+		public override function get text():String
+		{
+			// Get the text from the blockElement is there is one, otherwise grab it from the text property
+			var textValue:String = _blockElement ? _blockElement.rawText : _text;
+			
+			// test textLength cause this is a property and the debugger may run this calculation in intermediate states
+			if (textLength && hasParagraphTerminator)
+				return textValue.substr(0,textLength-1);
+				
+			return textValue != null ? textValue : "";
+		}
+		/** 
+		 * Receives the String of text that this SpanElement object holds.
+		 *
+		 * <p>The text of a span does not include the carriage return (CR) at the end of the paragraph
+		 * but it is included in the value of <code>textLength</code>.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	
+	 	public function set text(textValue:String):void
+		{
+			//original code stripped breaking and tab characters.  new code moved to collapseWhitevar newLineTabPattern:RegExp = /[\n\r\t]/g;
+			replaceText(0,textLength, textValue); 
+		} 
+		
+		/** @private */
+		public override function getText(relativeStart:int=0, relativeEnd:int=-1, paragraphSeparator:String="\n"):String
+		{
+			// Get the text from the blockElement is there is one, otherwise grab it from the text property
+			var textValue:String = _blockElement ? _blockElement.rawText : _text;
+
+			if (textLength && relativeEnd == textLength && hasParagraphTerminator)
+				--relativeEnd;		// don't include terminator
+			return textValue ? textValue.substring(relativeStart, relativeEnd) : "";
+		}
+
+		[RichTextContent]
+		/** 
+		 * Sets text based on content within span tags; always deletes existing children.
+		 * This property is intended for use during mxml compiled import. When TLF markup elements have other
+		 * TLF markup elements as children, the children are assigned to this property.
+		 *
+		 * @throws TypeError if array element is not a SpecialCharacterElement or a String
+		 * @param array - an array of elements within span tags. Each element of array must be a SpecialCharacterElement or a String.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function get mxmlChildren():Array
+		{
+			return [ text ];
+		}
+		public function set mxmlChildren(array:Array):void
+		{
+			/* NOTE: all FlowElement implementers and overrides of mxmlChildren must specify [RichTextContent] metadata */
+
+			var str:String = new String();
+			for each (var elem:Object in array)
+			{
+				if (elem is String)
+					str += elem as String;
+				else if (elem is Number)	// TODO: remove the Number else if when we can test with the most recent compilers.  The [RichTextContent] metadata fixes the issue
+					str += elem.toString();
+				else if (elem is BreakElement)
+					str += String.fromCharCode(0x2028);
+				else if (elem is TabElement)
+				{
+					// Add a placeholder (from Unicode private use area) instead of '\t' because the latter is 
+					// stripped during white space collapse. After white space collapse, we will change the placeholder
+					// to '\t' 
+					str += String.fromCharCode(0xE000); 
+				}	
+				else if (elem != null)
+					throw new TypeError(GlobalSettings.resourceStringFunction("badMXMLChildrenArgument",[ getQualifiedClassName(elem) ]));
+					
+			}
+			replaceText(0,textLength, str); 
+		}
+		
+		
+		/** 
+		 * Specifies whether this SpanElement object terminates the paragraph. The SpanElement object that terminates a 
+		 * paragraph has an extra, hidden character at the end. This character is added automatically by the component and is
+		 * included in the value of the <code>textLength</code> property.
+		 * 
+		 * @private */
+		 
+		tlf_internal function get hasParagraphTerminator():Boolean
+		{
+			var p:ParagraphElement = getParagraph();
+			return (p && p.getLastLeaf() == this); 
+		}
+		
+		/** @private */
+		CONFIG::debug tlf_internal function verifyParagraphTerminator():void
+		{
+			var str:String = _blockElement ? _blockElement.rawText : _text;
+			assert(str && str.length && str.charAt(str.length-1) == SpanElement.kParagraphTerminator,
+				"attempting to remove para terminator when it doesn't exist");
+		}
+		
+		
+		/**
+		 * Makes a shallow copy of this SpanElement between 2 character positions
+		 * and returns it as a FlowElement.  Unlike deepCopy, shallowCopy does
+		 * not copy any of the children of this SpanElement.
+		 * 
+		 */
+		 
+		 // If I have a sequence of different sorts of spaces (e.g., en quad, hair space), would I want them converted down to one space? Probably not.
+		 // For now, u0020 is the only space character we consider for eliminating duplicates, though u00A0 (non-breaking space) is potentially eligible. 
+		 private static const _dblSpacePattern:RegExp = /[\u0020]{2,}/g;
+		 // Tab, line feed, and carriage return
+		 private static const _newLineTabPattern:RegExp = /[\u0009\u000a\u000d]/g;
+		 private static const _tabPlaceholderPattern:RegExp = /\uE000/g;
+		 
+		 // static private const anyPrintChar:RegExp = /[^\s]/g;
+		 // Consider only tab, line feed, carriage return, and space as characters used for pretty-printing. 
+		 // While debatable, this is consistent with what CSS does. 
+		 static private const anyPrintChar:RegExp = /[^\u0009\u000a\u000d\u0020]/g; 
+
+		 /** @private */
+		tlf_internal override function applyWhiteSpaceCollapse():void
+		{
+			var stripValue:String = computedFormat.whiteSpaceCollapse;
+				
+			var tempTxt:String = text;
+				
+			if (!stripValue /* null == default value == COLLAPSE */ || stripValue == WhiteSpaceCollapse.COLLAPSE)
+			{
+				// The span was added automatically when a String was passed to replaceChildren.
+				// If it contains only whitespace, we remove the text.
+				if (impliedElement && parent != null)
+				{
+					// var matchArray:Array = tempTxt.search(anyPrintChar);
+					if (tempTxt.search(anyPrintChar) == -1)
+					{
+						parent.removeChild(this);
+						return;
+					}
+				}
+				
+				// For now, replace the newlines and tabs inside the element with a space.
+				// This is necessary for support of compiled mxml files that have newlines and tabs, because
+				// these are most likely not intended to be part of the text content, but only there so the
+				// text can be conveniently edited in the mxml file. Later on we need to add standalone elements
+				// for <br/> and <tab/>. Note that tab character is not supported in HTML.	
+				tempTxt = tempTxt.replace(_newLineTabPattern, " ");
+
+				// Replace sequences of 2 or more whitespace characters with single space
+				tempTxt = tempTxt.replace(_dblSpacePattern, " ");
+				}
+			
+			// Replace tab placeholders (used for tabs that are expected to survive whitespace collapse) with '\t'
+			replaceText(0, textLength, tempTxt.replace(_tabPlaceholderPattern, '\t'));
+
+			super.applyWhiteSpaceCollapse();
+		}
+		
+		/** 
+		 * Updates the text in text span based on the specified start and end positions. To insert text, set the end position
+		 * equal to the start position. To append text to the existing text in the span, set the start position and the
+		 * end position equal to the length of the existing text.
+		 *
+		 * <p>The replaced text includes the start character and up to but not including the end character.</p>
+		 * 
+		 *  @param relativeStartPosition The index position of the beginning of the text to be replaced, 
+		 *   relative to the start of the span. The first character in the span is at position 0.
+		 *  @param relativeEndPosition The index one position after the last character of the text to be replaced, 
+		 *   relative to the start of the span. Set this value equal to <code>relativeStartPos</code>
+		 *   for an insert. 
+		 *  @param textValue The replacement text or the text to add, as the case may be.
+		 * 
+		 *  @throws RangeError The <code>relativeStartPosition</code> or <code>relativeEndPosition</code> specified is out of 
+		 * range or a surrogate pair is being split as a result of the replace.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @includeExample examples/SpanElement_replaceTextExample.as -noswf
+		 */
+		 
+		public function replaceText(relativeStartPosition:int, relativeEndPosition:int, textValue:String):void
+		{
+			// Note to callers: If you are calling this function outside a try/catch, do ensure that the 
+			// state of the model is coherent before the call.
+			if (relativeStartPosition < 0 || relativeEndPosition > textLength || relativeEndPosition < relativeStartPosition)
+				throw RangeError(GlobalSettings.resourceStringFunction("invalidReplaceTextPositions"));	
+
+
+			var spanText:String = _blockElement ? _blockElement.rawText : _text;
+			if ((relativeStartPosition != 0 && relativeStartPosition != textLength && CharacterUtil.isLowSurrogate(spanText.charCodeAt(relativeStartPosition))) ||
+				(relativeEndPosition != 0 && relativeEndPosition != textLength && CharacterUtil.isHighSurrogate(spanText.charCodeAt(relativeEndPosition-1))))
+					throw RangeError (GlobalSettings.resourceStringFunction("invalidSurrogatePairSplit"));
+				
+			if (hasParagraphTerminator)
+			{
+				CONFIG::debug { assert(textLength > 0,"invalid span"); }
+				if (relativeStartPosition == textLength)
+					relativeStartPosition--;
+				if (relativeEndPosition == textLength)
+					relativeEndPosition--;
+			}
+			
+			if (relativeEndPosition != relativeStartPosition)
+				modelChanged(ModelChange.TEXT_DELETED,relativeStartPosition,relativeEndPosition-relativeStartPosition);
+			
+			replaceTextInternal(relativeStartPosition,relativeEndPosition,textValue);
+			
+			if (textValue && textValue.length)
+				modelChanged(ModelChange.TEXT_INSERTED,relativeStartPosition,textValue.length);
+		}
+		private function replaceTextInternal(startPos:int, endPos:int, textValue:String):void
+		{			
+			var textValueLength:int = textValue == null ? 0 : textValue.length;
+			var deleteTotal:int = endPos-startPos;
+			var deltaChars:int =  textValueLength - deleteTotal;
+			if (_blockElement)
+			{
+				TextElement(_blockElement).replaceText(startPos,endPos,textValue);
+				CONFIG::debug { Debugging.traceFTECall(null,TextElement(_blockElement),"replaceText",startPos,endPos,textValue); }
+			}
+			else if (_text)
+			{
+				if (textValue)
+					_text = _text.slice(0, startPos) + textValue + _text.slice(endPos, _text.length);
+				else
+					_text = _text.slice(0, startPos) + _text.slice(endPos, _text.length);
+			}
+			else
+				_text = textValue;
+			
+			if (deltaChars != 0)
+			{
+				updateLengths(getAbsoluteStart() + startPos, deltaChars, true);
+				deleteContainerText(endPos,deleteTotal);
+				
+				if (textValueLength != 0)
+				{
+					var enclosingContainer:ContainerController = getEnclosingController(startPos);
+					if (enclosingContainer)
+						ContainerController(enclosingContainer).setTextLength(enclosingContainer.textLength + textValueLength);
+				}
+			}
+
+			CONFIG::debug { 
+				var debugText:String = _blockElement == null ? _text : _blockElement.rawText;
+				assert(textLength == (debugText ? debugText.length : 0),"span textLength doesn't match the length of the text property, text property length is " + debugText.length.toString() + " textLength property is " + textLength.toString());
+			}
+		}
+	
+		/** @private */
+		tlf_internal override function addParaTerminator():void
+		{
+			CONFIG::debug 
+			{ 
+				// TODO: Is this assert valid? Do we prevent users from adding para terminators themselves? 
+				if (_blockElement && _blockElement.rawText && _blockElement.rawText.length)
+					assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) != SpanElement.kParagraphTerminator,"adding para terminator twice");
+			}
+
+			replaceTextInternal(textLength,textLength,SpanElement.kParagraphTerminator);
+			
+			CONFIG::debug 
+			{ 
+				// TODO: Is this assert valid? Do we prevent users from adding para terminators themselves? 
+				if (_blockElement)
+					assert(_blockElement.rawText.charAt(_blockElement.rawText.length-1) == SpanElement.kParagraphTerminator,"adding para terminator failed");
+			}			
+			
+			modelChanged(ModelChange.TEXT_INSERTED,textLength-1,1);
+		}
+		/** @private */
+		tlf_internal override function removeParaTerminator():void
+		{
+			CONFIG::debug 
+			{ 
+				var str:String = _blockElement ? _blockElement.rawText : _text;
+				assert(str && str.length && str.charAt(str.length-1) == SpanElement.kParagraphTerminator,
+					"attempting to remove para terminator when it doesn't exist");
+			}
+			replaceTextInternal(textLength-1,textLength,"");
+			modelChanged(ModelChange.TEXT_DELETED,textLength > 0 ? textLength-1 : 0,1);
+		}
+		// **************************************** 
+		// Begin tree modification support code
+		// ****************************************
+
+		/** 
+		 * Splits this SpanElement object at the specified position and returns a new SpanElement object for the content
+		 * that follows the specified position. 
+		 *
+		 * <p>This method throws an error if you attempt to split a surrogate pair. In Unicode UTF-16, a surrogate pair is a pair of 
+		 * 16-bit code units (a high code unit and a low code unit) that represent one of the abstract Unicode characters 
+		 * that cannot be represented in a single 16-bit word. The 16-bit high code unit is in the range of D800 to DBFF. The
+		 * 16-bit low code unit is in the range of DC00 to DFFF.</p>
+		 * 
+		 * @param relativePosition - relative position in the span to create the split
+		 * @return - the newly created span. 
+		 * @throws RangeError <code>relativePosition</code> is less than 0 or greater than textLength or a surrogate pair is being split.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @private
+	 	 */
+	 	 
+		public override function splitAtPosition(relativePosition:int):FlowElement
+		{
+			// Note to callers: If you are calling this function outside a try/catch, do ensure that the 
+			// state of the model is coherent before the call.
+			if (relativePosition < 0 || relativePosition > textLength)
+				throw RangeError(GlobalSettings.resourceStringFunction("invalidSplitAtPosition"));
+			
+			if ((relativePosition < textLength) && CharacterUtil.isLowSurrogate(String(text).charCodeAt(relativePosition)))
+				throw RangeError (GlobalSettings.resourceStringFunction("invalidSurrogatePairSplit"));
+			
+			var newSpan:SpanElement = new SpanElement();
+			// clone styling information
+			newSpan.id = this.id;
+			newSpan.styleName = this.styleName;			
+			
+			if (parent)
+			{
+				var newBlockElement:TextElement;
+				var newSpanLength:int = textLength - relativePosition;
+				if (_blockElement)
+				{
+				// optimized version leverages player APIs
+					// TODO: Jeff to add split on TextElement so we don't have to go find a group every time
+					var group:GroupElement = parent.createContentAsGroup();
+					
+					var elementIndex:int = group.getElementIndex(_blockElement);
+					
+					CONFIG::debug { assert(elementIndex == parent.getChildIndex(this),"bad group index"); }
+					CONFIG::debug { assert(elementIndex != -1 && elementIndex < group.elementCount,"bad span split"); }
+					//trace("GROUP BEFORE: " + group.rawText);
+					//trace("BLOCK BEFORE: " + group.block.content.rawText);
+					//trace("calling group.splitTextElement("+elementIndex.toString()+","+relativePosition.toString()+")");
+					group.splitTextElement(elementIndex, relativePosition);
+					CONFIG::debug { Debugging.traceFTECall(null,group,"splitTextElement",elementIndex,relativePosition); }
+
+					//trace("GROUP AFTER: " + group.rawText);
+					//trace("BLOCK AFTER: " + group.block.content.rawText);
+					
+					// no guarantee on how the split works
+					_blockElement = group.getElementAt(elementIndex);
+					CONFIG::debug { Debugging.traceFTECall(_blockElement,group,"getElementAt",elementIndex); }
+					newBlockElement = group.getElementAt(elementIndex+1) as TextElement;
+					CONFIG::debug { Debugging.traceFTECall(newBlockElement,group,"getElementAt",elementIndex+1); }
+				}
+				else if (relativePosition < textLength)
+				{
+					newSpan.text = _text.substr(relativePosition);
+					_text = _text.substring(0, relativePosition);
+				}
+
+				// Split this span at the offset, into two equivalent spans
+				modelChanged(ModelChange.TEXT_DELETED,relativePosition,newSpanLength);
+				newSpan.quickInitializeForSplit(this, newSpanLength,newBlockElement);
+
+				setTextLength(relativePosition);
+			
+				// slices it in, sets the parent and the start
+				parent.addChildAfterInternal(this,newSpan);	
+				newSpan.modelChanged(ModelChange.ELEMENT_ADDED,0,newSpan.textLength);
+			}
+			else
+			{
+				// this version also works if para is non-null but may not be as efficient.
+				newSpan.format = format;
+
+				// could be we are splitting 
+				if (relativePosition < textLength)
+				{
+					newSpan.text = String(this.text).substr(relativePosition);
+					replaceText(relativePosition,textLength,null);
+				}
+			}
+			
+			return newSpan;
+		}
+		
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			if (this.textLength == 1)
+			{
+				var p:ParagraphElement = getParagraph();
+				if (p && p.getLastLeaf() == this)
+				{
+					var prevLeaf:FlowLeafElement = getPreviousLeaf(p);
+					if (prevLeaf)
+					{
+						this.format = prevLeaf.format;
+						this.userStyles = prevLeaf.userStyles ? Property.shallowCopy(prevLeaf.userStyles) : null;
+					}
+				}
+			}
+			super.normalizeRange(normalizeStart,normalizeEnd);
+		}
+
+		/** @private */
+		tlf_internal override function mergeToPreviousIfPossible():Boolean
+		{
+			// if canReleaseContentElement is false than the contentElement has something special (like an eventMirror) and the span can't be merged
+			if (parent && !bindableElement && canReleaseContentElement())
+			{
+				var myidx:int = parent.getChildIndex(this);
+				if (myidx != 0)
+				{
+					var sib:SpanElement = parent.getChildAt(myidx-1) as SpanElement;
+					if (sib != null && sib.canReleaseContentElement() && 
+						(equalStylesForMerge(sib) || (this.textLength == 1 && this.hasParagraphTerminator)))
+					{
+						CONFIG::debug { assert(this.parent == sib.parent, "Should never merge two spans with different parents!"); }
+						CONFIG::debug { assert(TextLayoutFormat.isEqual(this.formatForCascade,sib.formatForCascade) || (this.textLength == 1 && this.hasParagraphTerminator), "Bad merge!"); }
+						
+						// Merge them in the Player's TextBlock structure
+						var siblingInsertPosition:int = sib.textLength;
+						sib.replaceText(siblingInsertPosition, siblingInsertPosition, this.text);
+						parent.replaceChildren(myidx,myidx+1,null);
+						return true;
+					}
+				}
+			} 
+			return false;
+		}
+		
+		// **************************************** 
+		// Begin debug support code
+		// ****************************************	
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			
+			var rslt:int = super.debugCheckFlowElement(depth,"text:"+String(text).substr(0,32)+" "+extraData);
+
+			var textValue:String = _blockElement ? _blockElement.rawText : _text;
+			var textLen:int = textLength;
+			if (textValue)
+				rslt += assert(textLen == textValue.length,"span is different than its textElement, span text length is " + textValue.length.toString() + " expecting " + textLen.toString());
+			else	
+				rslt += assert(textLen == 0,"span is different than its textElement, span text length is null expecting " + textLen.toString());
+			rslt += assert(this != getParagraph().getLastLeaf() || (textValue.length >= 1 && textValue.substr(textValue.length-1,1) == SpanElement.kParagraphTerminator),"last span in paragraph must end with terminator");
+			return rslt;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/SpecialCharacterElement.as b/textLayout_core/src/flashx/textLayout/elements/SpecialCharacterElement.as
new file mode 100755
index 0000000..709b36d
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/SpecialCharacterElement.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 flashx.textLayout.elements
+{
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.WhiteSpaceCollapse;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** The SpecialCharacterElement class is an abstract base class for elements that represent special characters.
+	 *
+	 * <p>You cannot create a SpecialCharacterElement object directly. Invoking <code>new SpecialCharacterElement()</code>
+	 * throws an error exception.</p>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see BreakElement
+	 * @see TabElement
+	 */
+	public class SpecialCharacterElement extends SpanElement
+	{
+		/**  
+		 * Base class - invoking <code>new SpecialCharacterElement()</code> throws an error exception.
+		 * 
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		 
+		public function SpecialCharacterElement()
+		{
+			super();
+		//	blockElement = new TextElement(null, null);
+						
+			// Set WhiteSpaceCollapse.PRESERVE to prevent merging with a sibling span with WhiteSpaceCollapse.COLLAPSE setting
+			// (during normalization). Otherwise the '\t' will be removed during the call to applyWhiteSpaceCollapse (following normalization).
+			// Once applyWhiteSpaceCollapse has been called, we can allow merging.
+			whiteSpaceCollapse = WhiteSpaceCollapse.PRESERVE; 
+		}
+		
+		/** @private */
+		tlf_internal override function mergeToPreviousIfPossible():Boolean
+		{
+			if (parent)
+			{
+				var myidx:int = parent.getChildIndex(this);
+				if (myidx != 0)
+				{
+					var sib:SpanElement = parent.getChildAt(myidx-1) as SpanElement;
+					if (sib != null && (sib is SpanElement) && TextLayoutFormat.isEqual(sib.format,format))
+					{
+						CONFIG::debug { assert(this.parent == sib.parent, "Should never merge two spans with different parents!"); }
+						
+						// Merge them in the Player's TextBlock structure
+						var siblingInsertPosition:int = sib.textLength;
+						sib.replaceText(siblingInsertPosition, siblingInsertPosition, this.text);
+						parent.replaceChildren(myidx,myidx+1);
+						return true;
+					}
+				}
+				// make a span and replace ourself
+				var newSib:SpanElement = new SpanElement();
+				newSib.text = this.text;
+				newSib.format = format;
+				parent.replaceChildren(myidx,myidx+1,newSib);
+				newSib.normalizeRange(0,newSib.textLength);
+				return false;
+			} 
+			return false;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/SubParagraphGroupElement.as b/textLayout_core/src/flashx/textLayout/elements/SubParagraphGroupElement.as
new file mode 100755
index 0000000..cb9bc20
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/SubParagraphGroupElement.as
@@ -0,0 +1,405 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import __AS3__.vec.Vector;
+	
+	import flash.events.EventDispatcher;
+	import flash.text.engine.ContentElement;
+	import flash.text.engine.GroupElement;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * The SubParagraphGroupElement class groups FlowLeafElements together. A SubParagraphGroupElement is a child of a 
+	 * ParagraphElement object and it can contain one or more FlowLeafElement objects as children.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 * 
+	 * @see FlowLeafElement
+	 * @see LinkElement
+	 * @see ParagraphElement
+	 * @see TCYElement
+	 */
+	 
+	public class SubParagraphGroupElement extends FlowGroupElement
+	{
+		private var _groupElement:GroupElement;
+		
+		/** @private - no listeners attached */
+		tlf_internal static const NO_ATTACHED_LISTENERS:uint       	= 0;
+		/** @private - only internal listeners attached */
+		tlf_internal static const INTERNAL_ATTACHED_LISTENERS:uint = 1;
+		/** @private - *may* be client attached listeners. */
+		tlf_internal static const CLIENT_ATTACHED_LISTENERS:uint   = 2;
+		
+		/** bit field describing attached listeners */
+		private var _attachedListenerStatus:uint;
+		
+		/** Maximum precedence value @private */
+		tlf_internal static const kMaxSPGEPrecedence:uint = 1000;
+		/** Minimum precedence value @private */
+		tlf_internal static const kMinSPGEPrecedence:uint = 0;
+		
+		private var _canMerge:Boolean; 	// true if element is bound to an external data source - generated text
+
+		/** Constructor - creates a new SubParagraphGroupElement instance.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public function SubParagraphGroupElement()
+		{
+			_canMerge = true;
+			_attachedListenerStatus = NO_ATTACHED_LISTENERS;
+			super();
+		}
+		
+		/** @private */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{
+			var retFlow:SubParagraphGroupElement = super.shallowCopy(startPos, endPos) as SubParagraphGroupElement;
+			if (_groupElement)
+				retFlow.createContentElement();
+			return retFlow;
+		}
+
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			if (_groupElement)
+				return;
+				
+			_groupElement = new GroupElement(null);
+			CONFIG::debug { Debugging.traceFTECall(_groupElement,null,"new GroupElement",null); }  
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				child.createContentElement();
+			}			
+			if (parent)
+				parent.insertBlockElement(this, _groupElement);
+		}
+		
+		/** @private */
+		override tlf_internal function releaseContentElement():void
+		{
+			if (!canReleaseContentElement() || groupElement == null)
+				return;
+			for (var i:int = 0; i < numChildren; i++)
+			{
+				var child:FlowElement = getChildAt(i);
+				child.releaseContentElement();
+			}			
+			_groupElement = null;
+		}
+		
+		/** @private */
+		override tlf_internal function canReleaseContentElement():Boolean
+		{
+			return _attachedListenerStatus == NO_ATTACHED_LISTENERS;
+		}
+		
+		/**
+		 * @public getter to return the precedence value of this SubParagraphGroupElement
+		 * Precedence is used to determine which SPGE element will be the container element
+		 * when two or more SPGEs of the same textLength are inside one another.
+		 * 
+		 * Precedence is used to determine which SubParagraphGroupElement is the owner when two or 
+		 * more elements have the same text and are embedded within each other.
+		 * 
+		 * Example: SPGEs A(precedence 900), B(precedence 400), C(precedence 600)
+		 * Model Result when all wrap SpanElement "123"
+		 * 
+		 * <A><C><B>123</B></C></A>
+		 * 
+		 * If two or more SPGE's have the same precedence value, then the alphabetic order is used:
+		 * Example: SPGE A(precedence 400), B(precedence 400), C(precedence 600)
+		 * 
+		 * <C><A><B>123</B></A></C>
+		 * 
+		 * Current values for SubParagraphGroupElements are:
+		 * 	LinkElement - 800
+		 * 	TCYElement - 100
+		 * 
+		 * If the value is not overriden by descendents of SPGE, then value is kMaxSPGEPrecedence;
+		 * @private
+		 */
+		tlf_internal function get precedence():uint { return kMaxSPGEPrecedence; }
+		
+		 
+		/** @private */
+		tlf_internal function get groupElement():GroupElement
+		{ return _groupElement; }
+		
+		/** @private */
+		tlf_internal function get attachedListenerStatus():int
+		{ return _attachedListenerStatus; }
+		
+		/** @private */
+		tlf_internal override function createContentAsGroup():GroupElement
+		{
+			return groupElement;
+		}
+		/** @private */
+		tlf_internal override function removeBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			var idx:int = this.getChildIndex(child);
+			groupElement.replaceElements(idx,idx+1,null);
+
+		}
+		
+		/** @private */
+		tlf_internal override function insertBlockElement(child:FlowElement, block:ContentElement):void
+		{
+			if (groupElement)
+			{
+				var idx:int = this.getChildIndex(child);
+				var gc:Vector.<ContentElement> = new Vector.<ContentElement>();
+				gc.push(block);
+				groupElement.replaceElements(idx,idx,gc);
+			}
+			else
+			{
+				child.releaseContentElement();
+				
+				var para:ParagraphElement = getParagraph();
+				if (para)
+					para.createTextBlock();
+			}
+		}
+		
+
+		/** @private */
+		tlf_internal override function hasBlockElement():Boolean
+		{
+			return groupElement != null;
+		}
+		
+		/** @private */
+		override tlf_internal function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
+		{
+			if (newParent == parent)
+				return;
+		
+			// remove textElement from the parent content
+			if (parent && parent.hasBlockElement() && groupElement)
+				parent.removeBlockElement(this,groupElement);
+			if (newParent && !newParent.hasBlockElement() && groupElement)
+				newParent.createContentElement();
+					
+			super.setParentAndRelativeStart(newParent,newStart);
+			
+			// Update the FTE ContentElement structure. If the parent has FTE elements, then create FTE elements for the leaf node 
+			// if it doesn't already have them, and add them in. If the parent does not have FTE elements, release the leaf's FTE
+			// elements also so they match.
+			if (parent && parent.hasBlockElement())
+			{
+				if (!groupElement)
+					createContentElement();
+				else
+					parent.insertBlockElement(this,groupElement);
+			}
+		}
+		
+		/** @private */
+		public override function replaceChildren(beginChildIndex:int,endChildIndex:int,...rest):void
+		{
+			var p:ParagraphElement = this.getParagraph();
+			
+			// are we replacing the last element?
+			var oldLastLeaf:FlowLeafElement = p ? p.getLastLeaf() : null;
+				
+			var applyParams:Array = [beginChildIndex, endChildIndex];
+			super.replaceChildren.apply(this, applyParams.concat(rest));
+			
+			if (p)
+				p.ensureTerminatorAfterReplace(oldLastLeaf);
+		}
+		
+		 /** @private
+		  * Returns the EventDispatcher associated with this SubParagraphGroupElement instance.  Use the functions
+		  * of EventDispatcher such as <code>addEventHandler()</code> and <code>removeEventHandler()</code> to 
+		  * capture events that happen over this SubParagraphGroupElement instance.  
+		  *
+		  * The event handling that you specify is called after this element does its processing.
+		  *
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+		  * @langversion 3.0
+		  *
+		  * @see flash.events.EventDispatcher
+		  * @see flash.text.engine.TextLineMirrorRegion
+		  */
+		  
+		tlf_internal function getEventMirror(statusMask:uint = CLIENT_ATTACHED_LISTENERS):EventDispatcher
+		{
+			if (!_groupElement)
+			{
+				var para:ParagraphElement = getParagraph();
+				if (para)
+					para.getTextBlock();
+				else
+					createContentElement();
+			}
+			if (_groupElement.eventMirror == null)
+			{				
+				_groupElement.eventMirror = new EventDispatcher();
+			}
+			_attachedListenerStatus |= statusMask;
+			return (_groupElement.eventMirror);
+		}
+
+		/** @private */
+		tlf_internal override function normalizeRange(normalizeStart:uint,normalizeEnd:uint):void
+		{
+			var idx:int = findChildIndexAtPosition(normalizeStart);
+			if (idx != -1 && idx < numChildren)
+			{
+				var child:FlowElement = getChildAt(idx);
+				normalizeStart = normalizeStart-child.parentRelativeStart;
+				
+				CONFIG::debug { assert(normalizeStart >= 0, "bad normalizeStart in normalizeRange"); }
+				for (;;)
+				{
+					// watch out for changes in the length of the child
+					var origChildEnd:int = child.parentRelativeStart+child.textLength;
+					child.normalizeRange(normalizeStart,normalizeEnd-child.parentRelativeStart);
+					var newChildEnd:int = child.parentRelativeStart+child.textLength;
+					normalizeEnd += newChildEnd-origChildEnd;	// adjust
+					
+					// no zero length children
+					if (child.textLength == 0 && !child.bindableElement)
+						replaceChildren(idx,idx+1);
+					else if (child.mergeToPreviousIfPossible())
+					{
+						var prevElement:FlowElement = this.getChildAt(idx-1);
+						// possibly optimize the start to the length of prevelement before the merge
+						prevElement.normalizeRange(0,prevElement.textLength);
+					}
+					else
+						idx++;
+
+					if (idx == numChildren)
+						break;
+					
+					// next child
+					child = getChildAt(idx);
+					
+					if (child.parentRelativeStart > normalizeEnd)
+						break;
+						
+					normalizeStart = 0;		// for the next child	
+				}
+			}
+			// empty subparagraphgroups not allowed after normalize
+			if (numChildren == 0 && parent != null)
+			{
+				var s:SpanElement = new SpanElement();
+				replaceChildren(0,0,s);
+				s.normalizeRange(0,s.textLength);
+			}
+		}
+
+		/** @private */
+		tlf_internal override function canOwnFlowElement(elem:FlowElement):Boolean
+		{
+			// Only allow sub-paragraph group elements (with restrictions) and leaf elements 
+			if (elem is FlowLeafElement)
+				return true;
+			
+			var subParagraphGroupElem:SubParagraphGroupElement = elem as SubParagraphGroupElement;
+			if (subParagraphGroupElem)
+			{ 
+				// Sub-paragraph group elements of the same kind cannot nest, even indirectly.
+				// For example, a link cannot contain a link, nor can it contain a TCY whose child is a link and so on.				
+				// We assume that the two trees being joined are themselves valid, so the above rule can only be violated if
+				// a) elem's type is same as my type
+				// b) elem's type is same as my parent's type
+				// c) an elem's child's type is same as my type
+				// [Note: this is valid only because we have just two kinds of sub-paragraph groups. Any more, and we'll need more
+				// complex rules]  
+
+				var myClass:String = getQualifiedClassName(this);
+				var elemClass:String = getQualifiedClassName(elem);
+				var parentClass:String = parent ? getQualifiedClassName(parent) : null;
+				
+				if (elemClass == myClass || elemClass == parentClass)
+					return false;
+					
+				for (var i:int=0; i<subParagraphGroupElem.numChildren; i++)
+				{
+					if (getQualifiedClassName(subParagraphGroupElem.getChildAt(i)) == myClass)
+						return false;
+				}
+				
+				return true;
+			}
+			
+			return false;
+		}
+		
+		/** Helper function for determination of where text should be inserted.  In the case of LinkElements,
+		 * text inserted before the LinkElement and text inserted after the LinkElement should not become
+		 * par of the link.  However, for most other SubParagraphGroupElements, inserted text should become
+		 * part of the SubParagraphGroupElement.
+		 * @private
+		 * */
+		tlf_internal function acceptTextBefore():Boolean 
+		{ 
+			return true; 
+		}
+		
+		/** Helper function for determination of where text should be inserted.  In the case of LinkElements,
+		 * text inserted before the LinkElement and text inserted after the LinkElement should not become
+		 * par of the link.  However, for most other SubParagraphGroupElements, inserted text should become
+		 * part of the SubParagraphGroupElement.
+		 * @private
+		 * */
+		tlf_internal function acceptTextAfter():Boolean
+		{
+			return true;
+		}
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			var rslt:int = super.debugCheckFlowElement(depth," fte:"+getDebugIdentity(groupElement)+" "+extraData);
+			rslt += assert(getParagraph() != null && (parent is ParagraphElement || parent is SubParagraphGroupElement), "SubParagraphGroupElement must be nested in a pargraph");
+			
+			//groupElement can be null if the Paragraph is overset or not yet composed.  Don't check elementCount - Watson 2283828
+			if(this.groupElement)
+				rslt += assert(this.groupElement.elementCount == this.numChildren,"Bad element count in SubParagraphGroupElement");
+				
+			if (parent is ParagraphElement)
+				rslt += assert(this.groupElement != ParagraphElement(parent).getTextBlock().content,"Bad group");
+			return rslt; 
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/TCYElement.as b/textLayout_core/src/flashx/textLayout/elements/TCYElement.as
new file mode 100755
index 0000000..f0086e1
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/TCYElement.as
@@ -0,0 +1,182 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextRotation;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * The TCYElement (Tatechuuyoko - ta-tae-chu-yo-ko) class is a subclass of SubParagraphGroupElement that causes
+	 * text to draw horizontally within a vertical line.  Traditionally, it is used to make small
+	 * blocks of non-Japanese text or numbers, such as dates, more readable.  TCY can be applied to 
+	 * horizontal text, but has no effect on drawing style unless and until it is turned vertically.
+	 * 
+	 * TCY blocks which contain no text will be removed from the text flow during the normalization process.
+	 * <p>
+	 * In the example below, the image on the right shows TCY applied to the number 57, while the
+	 * image on the left has no TCY formatting.</p>
+	 * <p><img src="../../../images/textLayout_TCYElement.png" alt="TCYElement" border="0"/>
+	 * </p>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see TextFlow
+	 * @see ParagraphElement
+	 * @see SpanElement
+	 */
+	public final class TCYElement extends SubParagraphGroupElement
+	{
+		/** Constructor - creates a new TCYElement instance.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 */
+		public function TCYElement()
+		{
+			super();
+		}
+		
+		/** @private */
+		override tlf_internal function createContentElement():void
+		{
+			super.createContentElement();
+			updateTCYRotation();
+		}
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+		/** @private */
+        tlf_internal override function get precedence():uint { return 100; }
+		
+		/** @private */
+		tlf_internal override function mergeToPreviousIfPossible():Boolean
+		{	
+			if (parent && !bindableElement)
+			{
+				var myidx:int = parent.getChildIndex(this);
+				if (myidx != 0)
+				{
+					var prevEl:TCYElement = parent.getChildAt(myidx - 1) as TCYElement;
+					if(prevEl)
+					{
+						while(this.numChildren > 0)
+						{
+							var xferEl:FlowElement = this.getChildAt(0);
+							replaceChildren(0, 1);
+							prevEl.replaceChildren(prevEl.numChildren, prevEl.numChildren, xferEl);
+						}
+						parent.replaceChildren(myidx, myidx + 1);								
+						return true;
+					}		
+				}
+			}
+			
+			return false;
+		}
+		
+		/** @private */
+		tlf_internal override function acceptTextBefore():Boolean 
+		{ 
+			return false; 
+		}
+		
+		/** @private */
+		tlf_internal override function setParentAndRelativeStart(newParent:FlowGroupElement,newStart:int):void
+		{
+			super.setParentAndRelativeStart(newParent,newStart);
+			updateTCYRotation();
+		}
+		
+		/** @private */
+		tlf_internal override function formatChanged(notifyModelChanged:Boolean = true):void
+		{
+			super.formatChanged(notifyModelChanged);
+			updateTCYRotation();
+		}
+		
+		/** @private */
+		tlf_internal function calculateAdornmentBounds(spg:SubParagraphGroupElement, tLine:TextLine, blockProgression:String, spgRect:Rectangle):void
+		{
+			var childCount:int = 0;
+			while(childCount < spg.numChildren)
+			{
+				var curChild:FlowElement = spg.getChildAt(childCount) as FlowElement;
+				var curFlowLeaf:FlowLeafElement = curChild as FlowLeafElement;
+				if(!curFlowLeaf && curChild is SubParagraphGroupElement)
+				{
+					calculateAdornmentBounds(curChild as SubParagraphGroupElement, tLine, blockProgression, spgRect);
+					++childCount;
+					continue;
+				}
+				
+				CONFIG::debug{ assert(curFlowLeaf != null, "The TCY contains a non-FlowLeafElement!  Cannot calculate mirror!")};
+				var curBounds:Rectangle = null;
+				if(!(curFlowLeaf is InlineGraphicElement))
+					curBounds = curFlowLeaf.getSpanBoundsOnLine(tLine, blockProgression)[0];
+				else
+				{
+					curBounds = (curFlowLeaf as InlineGraphicElement).graphic.getBounds(tLine);
+				}
+				
+				if(childCount != 0)
+				{
+					if(curBounds.top < spgRect.top)
+						spgRect.top = curBounds.top;
+						
+					if(curBounds.bottom > spgRect.bottom)
+						spgRect.bottom = curBounds.bottom;
+					
+					if(spgRect.x > curBounds.x)
+						spgRect.x = curBounds.x;
+				}
+				else
+				{
+					spgRect.top = curBounds.top;
+					spgRect.bottom = curBounds.bottom;
+					spgRect.x = curBounds.x;
+				}
+				++childCount;
+			}
+		}
+		
+		/** @private */
+		private function updateTCYRotation():void
+		{
+			var contElement:ContainerFormattedElement = getAncestorWithContainer();
+			if (groupElement)
+				groupElement.textRotation = (contElement && contElement.computedFormat.blockProgression == BlockProgression.RL) ? TextRotation.ROTATE_270 : TextRotation.ROTATE_0;	
+		}
+	}
+	
+	
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/TabElement.as b/textLayout_core/src/flashx/textLayout/elements/TabElement.as
new file mode 100755
index 0000000..30596a5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/TabElement.as
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.text.engine.TextElement;
+	
+	/** 
+	 * The TabElement class represents a &lt;tab/&gt; in the text flow. You assign tab stops as an array of TabStopFormat objects to the 
+	 * <code>ParagraphElement.tabStops</code> property.
+	 * 
+	 * <p><strong>Note</strong>:This class exists primarily to support &lt;tab/&gt; in MXML markup. You can add tab characters (\t) directly 
+	 * into the text like this:</p>
+	 *
+	 * <listing version="3.0" >
+	 * spanElement1.text += '\t';
+	 * </listing>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see flashx.textLayout.formats.TabStopFormat
+	 * @see FlowElement#tabStops
+	 * @see SpanElement
+	 */
+	 
+	public final class TabElement extends SpecialCharacterElement
+	{
+		/** Constructor - creates a new TabElement instance. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TabElement()
+		{
+			super();
+			this.text = '\t';
+		}			
+		
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/elements/TextFlow.as b/textLayout_core/src/flashx/textLayout/elements/TextFlow.as
new file mode 100755
index 0000000..0f86825
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/TextFlow.as
@@ -0,0 +1,1232 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.IEventDispatcher;
+	import flash.text.engine.TextLineValidity;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.compose.FlowComposerBase;
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.ISWFContext;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.DamageEvent;
+	import flashx.textLayout.events.ModelChange;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.textLayout.external.WeakRef;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	/**
+	 *
+	 *  @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_BEGIN
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	[Event(name="flowOperationBegin", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	/**
+	 * 
+	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_END
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	[Event(name="flowOperationEnd", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	/**
+	 * 
+	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_COMPLETE
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="flowOperationComplete", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	/** Dispatched whenever the selection is changed.  Primarily used to update selection-dependent user interface. 
+	 * It can also be used to alter the selection, but cannot be used to alter the TextFlow itself.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="selectionChange", type="flashx.textLayout.events.SelectionEvent")]
+	
+	/** Dispatched after every recompose. 
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*/
+	
+	[Event(name="compositionComplete", type="flashx.textLayout.events.CompositionCompleteEvent")]
+	
+	/** Dispatched when the mouse is pressed down over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseDown", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse is released over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseUp", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse passes over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseMove", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	
+	/** Dispatched when the mouse first enters any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="rollOver", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse goes out of any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="rollOut", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	
+	/** Dispatched when any link is clicked. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="click", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when a InlineGraphicElement is resized due to having width or height as auto or percent 
+	 * and the graphic has finished loading. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="inlineGraphicStatusChanged", type="flashx.textLayout.events.StatusChangeEvent")]
+	
+	/** Dispatched by a TextFlow object after text is scrolled within a controller container.  
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="scroll", type="flashx.textLayout.events.TextLayoutEvent")]
+	
+	/** Dispatched by a TextFlow object each time it is damaged 
+	 * 
+	 * You can use this event to find out that the TextFlow has changed, but do not access the TextFlow itself when this event 
+	 * is sent out. This event is sent when TextFlow changes are partially complete, so it can be in an inconsistent state: 
+	 * some changes have been mad already, and other changes are still pending. Get the information you need from the event, and make 
+	 * required changes after control returns to your application.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="damage", type="flashx.textLayout.events.DamageEvent")]
+
+	/** Dispatched by a TextFlow object each time a container has had new DisplayObjects added or updated as a result of composition.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="updateComplete", type="flashx.textLayout.events.UpdateCompleteEvent")]
+
+
+	/**
+	 * 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>A TextFlow object can have ParagraphElement and DivElement objects as children. A div (DivElement object)
+	 * represents a group of paragraphs (ParagraphElement objects). A paragraph can have SpanElement, InlineGraphicElement, 
+	 * LinkElement, and TCYElement objects as children.</p>
+	 * 
+	 * <p>A span (SpanElement) is a range of text in a paragraph that has the same attributes. An image 
+	 * (InlineGraphicElement) represents an arbitrary graphic that appears as a single character in a line of text. A 
+	 * LinkElement represents a hyperlink, or HTML <code>a</code> tag, and it can contain multiple spans. A TCYElement object
+	 * is used in Japanese text when there is a small run of text that appears perpendicular to the line, as in a horizontal
+	 * run within a vertical line. A TCYElement also can contain multiple spans.</p>
+	 
+	 * <p>TextFlow also derives from the ContainerFormattedElement class, which is the root class for all container-level block 
+	 * elements.</p>
+ 	 * <p>The following illustration shows the relationship of other elements, such as spans and paragraphs, to the TextFlow 
+ 	 * object.</p>
+ 	 * <p><img src="../../../images/textLayout_textFlowHierarchy.gif" alt="example TextFlow hierarchy"></img></p>
+ 	 *
+ 	 * <p>Each TextFlow object has a corresponding Configuration object that allows you to specify initial character and 
+ 	 * paragraph formats and the initial container format. It also allows you to specify attributes for selection, links, 
+ 	 * focus, and scrolling. When you supply a Configuration object as parameter to the <code>TextFlow()</code>
+ 	 * constructor, it creates a read-only snapshot that you can access through the <code>TextFlow.configuration</code>
+ 	 * property. After creation, you can't change the TextFlow's configuration. If you do not specify a Configuration, you 
+ 	 * can access the default configuration through the <code>TextFlow.defaultConfiguration</code> property.</p>
+	 *
+	 * @includeExample examples\TextFlowExample.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see #configuration
+	 * @see IConfiguration
+	 * @see DivElement
+	 * @see FlowElement
+	 * @see FlowGroupElement
+	 * @see FlowLeafElement
+	 * @see flashx.textLayout.compose.IFlowComposer IFlowComposer
+	 * @see ParagraphElement
+	 * @see SpanElement
+	 */
+	 
+	public class TextFlow extends ContainerFormattedElement implements IEventDispatcher
+	{		
+		private var _flowComposer:IFlowComposer;
+		
+		/** References the Selection manager attached to this TextFlow object. */
+		private var _interactionManager:ISelectionManager;
+		
+		/** References the Configuration object for this TextFlow object. */
+		
+		private var _configuration:IConfiguration;
+		
+		/** Manages computing and drawing backgroundColor attribute */
+		private var _backgroundManager:BackgroundManager;
+		
+		/** Default configuration for all new TextFlow objects if the configuration is not specified. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see Configuration
+		 */
+		
+		public static var defaultConfiguration:Configuration = new Configuration();
+				
+		// normalize support
+		private var normalizeStart:int = 0;
+		private var normalizeLen:int = 0;
+		
+		// event dispatch support
+		private var _eventDispatcher:EventDispatcher;
+		
+		// textflow specific generation support - used to validate undo
+		private var _generation:uint;
+		// next generation number to hand out - these just have to be unique so share one.
+		// 0 is reserved to mean "not set"
+		static private var _nextGeneration:uint = 1;
+		
+		// styling support
+		private var _formatResolver:IFormatResolver;
+				
+		/** 
+		 * Constructor - creates a new TextFlow instance.
+		 *
+		 * <p>If you provide a <code>config</code> parameter, the contents of the Configuration object are copied and
+		 * you cannot make changes. You can access configuration settings, however, through the 
+		 * <code>configuration</code> property. If the <code>config</code> parameter is null, you can access the default
+		 * configuration settings through the <code>defaultConfiguration</code> property.</p> 
+		 *
+		 * <p>The Configuration object provides a mechanism for setting configurable default attributes on a TextFlow.  
+		 * While you can't make changes to the Configuration object, you can override default attributes, if necessary, 
+		 * by setting the attributes of TextFlow and its children.</p>
+		 * 
+		 * @param config Specifies the configuration to use for this TextFlow object. If it's null, use 
+		 * <code>TextFlow.defaultConfiguration</code> to access configuration values. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see Configuration
+	 	 * @see #configuration
+	 	 * @see #defaultConfiguration
+		 * 
+		 */
+		 
+		public function TextFlow(config:IConfiguration = null)
+		{
+			super();
+			initializeForConstructor(config);
+		}
+		
+		private function initializeForConstructor(config:IConfiguration):void
+		{
+			if (config == null)
+				config = defaultConfiguration;
+			// read only non changing copy of current state
+			_configuration = Configuration(config).getImmutableClone();
+			_eventDispatcher = new EventDispatcher(this);
+	
+			format = _configuration.textFlowInitialFormat;
+			
+			// initialize the flowComposer
+			if (_configuration.flowComposerClass)
+				flowComposer = new _configuration.flowComposerClass();
+			
+			_generation = _nextGeneration++;
+		}
+		
+		/** @private */
+		public override function shallowCopy(startPos:int = 0, endPos:int = -1):FlowElement
+		{		
+			var retFlow:TextFlow = super.shallowCopy(startPos, endPos) as TextFlow;
+			retFlow._configuration = _configuration;
+			retFlow._generation = _nextGeneration++;
+			if (formatResolver)
+				retFlow.formatResolver = formatResolver.getResolverForNewFlow(this,retFlow);
+			// TODO: preserve the hostFormat??
+			// preserve the swfContext
+			if (retFlow.flowComposer && flowComposer)
+				retFlow.flowComposer.swfContext = flowComposer.swfContext;
+			return retFlow;						
+		}
+		
+		/** 
+		* The Configuration object for this TextFlow object. The Configuration object specifies the initial character 
+		* and paragraph formats, the initial container format, and attributes for selection highlighting, 
+		* links, focus, and scrolling.
+		*
+		* <p>If you do not specify a Configuration object, Text Layout Framework uses a default Configuration object, which
+		* is referenced by the <code>defaultConfiguration</code> property.</p>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see Configuration
+	 	* @see #defaultConfiguration
+	 	*/
+		public function get configuration():IConfiguration
+		{ return _configuration; }
+
+		/**
+		 * The InteractionManager associated with this TextFlow object.
+		 * <p>Controls all selection and editing on the text. If the TextFlow is not selectable, 
+		 * the interactionManager is null. To make the TextFlow editable, assign a interactionManager
+		 * that is both an ISelectionManager and an IEditManager. To make a TextFlow that is read-only
+		 * and allows selection, assign a interactionManager that is an ISelectionManager only. </p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flashx.textLayout.edit.ISelectionManager ISelectionManager
+		 * @see flashx.textLayout.edit.IEditManager IEditManager
+		 */
+		public function get interactionManager():ISelectionManager
+		{
+			return _interactionManager;
+		}
+		public function set interactionManager(newInteractionManager:ISelectionManager):void
+		{
+			// detatch old interactionManager
+			if (_interactionManager != newInteractionManager)
+			{
+				if (_interactionManager)
+					_interactionManager.textFlow = null;
+				_interactionManager = newInteractionManager;
+				if (_interactionManager)
+					_interactionManager.textFlow = this;
+				if (flowComposer)
+					flowComposer.interactionManagerChanged(newInteractionManager);
+			}
+		}
+		
+		/** Manages the containers for this element.
+		 * 
+		 * <p>The TextLines that are created from the element appear as children of the container.
+		 * The flowComposer manages the containers, and as the text is edited it adds lines to and removes lines
+		 * from the containers. The flowComposer also keeps track of some critical attributes, such as the
+		 * width and height to compose to, whether scrolling is on, and so on.</p>
+		 * 
+		 * <p>The container and <code>flowComposer</code> are closely related. If you reset <code>flowComposer</code>, 
+		 * the container is reset to the new flowComposer's container. Likewise if the container is reset, 
+		 * <code>flowComposer</code> is reset to the container's new flowComposer.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.compose.IFlowComposer FlowComposer
+		 */
+		public override function get flowComposer():IFlowComposer
+		{ 
+			return _flowComposer; 
+		}
+		
+		public function set flowComposer(composer:IFlowComposer):void
+		{
+			changeFlowComposer(composer,true);
+		}
+		
+		/** @private */
+		tlf_internal function changeFlowComposer(newComposer:IFlowComposer,okToUnloadGraphics:Boolean):void
+		{
+			if (_flowComposer != newComposer)
+			{
+				var oldSWFContext:ISWFContext = FlowComposerBase.computeBaseSWFContext(_flowComposer ? _flowComposer.swfContext : null);
+				var newSWFContext:ISWFContext = FlowComposerBase.computeBaseSWFContext(newComposer ? newComposer.swfContext : null);					
+				
+				// no flowComposer on the clipboard - we should really delay this until the flowComposer gets its first container and 
+				if (!flowComposer && newComposer || flowComposer && !newComposer)
+					appendElementsForDelayedUpdate(this);
+				
+				// Clear out old settings
+				if (_flowComposer)
+				{
+					//hideSelection is no longer on IFlowComposer, so do it manually
+					var containerIter:int = 0;
+					while(containerIter < _flowComposer.numControllers)
+					{
+						_flowComposer.getControllerAt(containerIter++).clearSelectionShapes();
+					}
+					
+					_flowComposer.setRootElement(null); 	// clear event listeners
+				}
+
+				_flowComposer = newComposer;
+	
+				if (_flowComposer)
+					_flowComposer.setRootElement(this);
+					
+				// Mark flow as damaged
+				if (textLength)
+					damage(getAbsoluteStart(), textLength, TextLineValidity.INVALID, false);
+				
+				if (oldSWFContext != newSWFContext)
+					invalidateAllFormats();
+	
+				// containers *may* have changed requiring reinherit of columnDirection/blockProgression
+				// but that's only in the case when we have ContainerFormattedElements that can have containers -- if then
+				// this call is really expensive for long flows and needs to be optimized for cases when nothing changes
+				// containerFormatChanged(false);
+
+				// no longer visible shut down all the FEs
+				if (flowComposer == null)
+					applyUpdateElements(okToUnloadGraphics);
+			}
+		}
+		
+		/** Returns an element whose <code>id</code> property matches the <code>idName</code> parameter. Provides
+		 * the ability to apply a style based on the <code>id</code>. 
+		 *
+		 * <p>For example, the following line sets the style "color" to 0xFF0000 (red), for the
+		 * element having the <code>id</code> span1.</p>
+		 *
+		 * <listing version="3.0" >
+		 * textFlow.getElementByID("span1").setStyle("color", 0xFF0000);
+		 * </listing>
+		 *
+		 * <p><strong>Note:</strong> In the following code, <code>p.addChild(s)</code> <em>removes</em> <code>s</code> 
+		 * from its original parent and adds it to <code>p</code>, the new parent.</p>
+		 *
+		 * <listing version="3.0" >
+		 * var s:SpanElement = new SpanElement();
+		 * var p:ParagraphElement = new ParagraphElement();
+		 * ...
+		 * s = textFlow.getElementByID("span3") as SpanElement;
+		 * p.addChild(s);
+		 * textFlow.addChild(p);
+		 * </listing>
+		 *
+		 * @param idName The <code>id</code> value of the element to find.
+		 *
+		 * @return The element whose id matches <code>idName</code>.
+		 *
+		 * @includeExample examples\TextFlow_getElementByIDExample.as -noswf
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 *
+		 * @see FlowElement#id 
+		 */
+		
+		public function getElementByID(idName:String):FlowElement
+		{
+			return getElementByIDHelper(idName);
+		}
+		
+		/** Returns all elements that have <code>styleName</code> set to <code>styleNameValue</code>.
+		 *
+		 * @param styleNameValue The name of the style for which to find elements that have it set.
+		 *
+		 * @return An array of the elements whose <code>styleName</code> value matches <code>styleNameValue</code>. For example,
+		 * all elements that have the style name "color".
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 *
+		 * @see FlowElement#styleName 
+		 */
+		public function getElementsByStyleName(styleNameValue:String):Array
+		{
+			var a:Array = new Array;
+			getElementsByStyleNameHelper(a,styleNameValue);
+			return a;
+		}
+
+		/** @private */
+		override protected function get abstract():Boolean
+		{
+			return false;
+		}		
+		
+		/** @private */
+		tlf_internal override function updateLengths(startIdx:int,len:int,updateLines:Boolean):void
+		{
+			if (normalizeStart != -1)
+			{
+				var newNormalizeStart:int = startIdx < normalizeStart ? startIdx : normalizeStart;
+
+				if (newNormalizeStart < normalizeStart)
+					normalizeLen += (normalizeStart-newNormalizeStart);
+				normalizeLen += len;
+				normalizeStart = newNormalizeStart;
+			}
+			else
+			{
+				normalizeStart = startIdx;
+				normalizeLen   = len;
+			}
+			// never go below zero
+			if (normalizeLen < 0)
+				normalizeLen = 0;
+			
+			// fix the lines
+			if (updateLines && _flowComposer)
+			{
+				_flowComposer.updateLengths(startIdx,len);
+				super.updateLengths(startIdx,len, false);
+			}
+			else
+				super.updateLengths(startIdx,len,updateLines);
+		}
+		
+		[RichTextContent]
+		/** @private NOTE: all FlowElement implementers and overrides of mxmlChildren must specify [RichTextContent] metadata */
+		public override function set mxmlChildren(array:Array):void
+		{
+			super.mxmlChildren = array; 
+			normalize();
+			applyWhiteSpaceCollapse();
+		} 
+		
+		/** @private Update any elements that have a delayed updated.  Normally used to stop and stop foreignelements when they 
+		 * are either displayed the first time or removed from the stage
+		 */
+		tlf_internal function applyUpdateElements(okToUnloadGraphics:Boolean):Boolean
+		{
+			if (_elemsToUpdate)
+			{
+				var hasController:Boolean = flowComposer && flowComposer.numControllers != 0;
+				for each (var child:FlowElement in _elemsToUpdate)
+					child.applyDelayedElementUpdate(this,okToUnloadGraphics,hasController);
+				_elemsToUpdate = null;	// expect this array is transient
+				return true;
+			}
+			return false;
+		}
+		
+		/** @private */
+		tlf_internal override function preCompose():void
+		{
+			// normalizes the flow
+			do 
+			{
+				normalize();
+			}	
+				// starts or stops any FEs that have been modified, removed or deleted
+			while (applyUpdateElements(true));
+			
+			// need to call normalize again in case any of the element updates have modified the hierarchy
+			// normalize();
+		}
+	
+		/**
+		 * Mark the a range of text as invalid - needs to be recomposed.
+		 * <p>The text classes are self damaging.  This is only used when modifying the container chain.</p>
+		 * <p>Warning: Plan to evaulate a way to hide this method totally.</p>
+		 * @param start		text index of first character to marked invalid
+		 * @param damageLen	number of characters to mark invalid
+		 * @param needNormalize optional parameter (true is default) - normalize should include this range.
+		 * @private
+		 */
+		tlf_internal function damage(damageStart:int, damageLen:int, damageType:String, needNormalize:Boolean = true):void
+		{
+			CONFIG::debug { assert(damageLen > 0,"must have at least 1 char in damageLen"); }
+				
+			if (needNormalize)
+			{
+				if (normalizeStart == -1)
+				{
+					normalizeStart = damageStart;
+					normalizeLen   = damageLen;
+				}
+				else
+				{
+					if (damageStart < normalizeStart)
+					{
+						var newNormalizeLen:uint = normalizeLen;
+						newNormalizeLen = normalizeStart+normalizeLen - damageStart;
+						if (damageLen > newNormalizeLen)
+							newNormalizeLen = damageLen;
+						normalizeStart = damageStart;
+						normalizeLen = newNormalizeLen;
+					}
+					else if ((normalizeStart+normalizeLen) > damageStart)
+					{
+						if (damageStart+damageLen > normalizeStart+normalizeLen)
+							normalizeLen = damageStart+damageLen-normalizeStart;
+					}
+					else
+						normalizeLen = damageStart+damageLen-normalizeStart;
+				}
+				
+				// clamp to textLength
+				CONFIG::debug { assert(normalizeStart <= textLength,"damage bad length"); }
+				if (normalizeStart+normalizeLen > textLength)
+					normalizeLen = textLength-normalizeStart;
+				// trace("damage damageStart:" + damageStart.toString() + " damageLen:" + damageLen.toString() + " textLength:" + this.textLength + " normalizeStart:" + normalizeStart.toString() + " normalizeLen:"  + normalizeLen.toString() );
+			}
+			
+			if (_flowComposer)
+				_flowComposer.damage(damageStart, damageLen, damageType);
+				
+			if (hasEventListener(DamageEvent.DAMAGE))
+				dispatchEvent(new DamageEvent(DamageEvent.DAMAGE,false,false,this,damageStart,damageLen));
+		}
+			
+		/**
+		 * Find the paragraph at the specified absolute position
+		 * @private
+		 */
+		tlf_internal function findAbsoluteParagraph(pos:int):ParagraphElement
+		{
+			var elem:FlowElement = findLeaf(pos);
+			return elem ? elem.getParagraph() : null;
+		}
+
+		/**
+		 * Find the FlowGroupElement at the absolute position,
+		 * could be synonymous with the paragraph OR a subBlockElement
+		 * @private
+		 */
+		 tlf_internal function findAbsoluteFlowGroupElement(pos:int):FlowGroupElement
+		 {
+		 	var elem:FlowElement = findLeaf(pos);
+		 	return elem.parent;
+		 }
+		
+		/** @private */
+		CONFIG::debug public override function debugCheckFlowElement(depth:int = 0, extraData:String = ""):int
+		{
+			// debugging function that asserts if the flow element tree is in an invalid state
+			
+			var rslt:int = super.debugCheckFlowElement(depth,extraData);
+			
+			// describe the lines
+			if (Debugging.verbose && flowComposer)
+			{
+				for ( var lineIdx:int = 0; lineIdx < flowComposer.numLines; lineIdx++)
+				{
+					var workLine:TextFlowLine = flowComposer.getLineAt(lineIdx);
+					var containerIdx:int = flowComposer.getControllerIndex(workLine.controller);
+					trace("line:",lineIdx,"controller:",containerIdx,workLine.toString());
+				}
+				
+				for (var idx:int = 0; idx < flowComposer.numControllers; idx++)
+				{
+					var controller:ContainerController = flowComposer.getControllerAt(idx);
+					trace("controller:",idx,Debugging.getIdentity(controller),controller.absoluteStart,controller.textLength,controller.compositionWidth,controller.compositionHeight,controller.getContentBounds());
+				}
+			}
+			
+			rslt += assert(parent == null, "TextFlow should not have a parent");
+			rslt += assert(parentRelativeStart == 0, "TextFlow start not zero");
+
+			return rslt;		
+		}
+		
+		/**
+		 * Check the internal consistency of the flow's FlowElement tree.
+		 * @private
+		 * Asserts if the data structures in the flow are invalid.
+		 */
+		CONFIG::debug public function debugCheckTextFlow(validateControllers:Boolean=true):int
+		{
+			var rslt:int = debugCheckFlowElement();
+			
+			if (_flowComposer && validateControllers)
+			{
+				var idx:int;
+				var endPrevController:int = 0;
+				for (idx = 0; idx < flowComposer.numControllers; idx++)
+				{
+					var controller:ContainerController = flowComposer.getControllerAt(idx);
+					if (Debugging.verbose)
+					{
+						trace("controller:",idx,"absoluteStart:",controller.absoluteStart,"textLength:",controller.textLength);
+					}
+					
+					rslt += assert(controller.absoluteStart == endPrevController, "controller has bad start");
+					rslt += assert(controller.textLength >= 0, "controller has bad textLength");
+					endPrevController = controller.absoluteStart+controller.textLength;
+					rslt += assert(endPrevController <= textLength, "textLength may not extend past end of root element!");
+				}
+			}
+			
+			if (_flowComposer is StandardFlowComposer)
+				rslt += StandardFlowComposer(_flowComposer).debugCheckTextFlowLines(validateControllers);
+			return rslt;
+		}
+		
+		/**
+		 * Called after an import to validate that the entire flow textLength needs normalize.
+		 * @private
+		 */
+		 CONFIG::debug public function debugCheckNormalizeAll():void
+		{
+			assert(normalizeStart == 0,"normalizeStart: bad normailzeStart");
+			assert(normalizeLen == textLength,"debugCheckNormalizeAll: bad normalizeLen");
+		}
+		
+		/**
+		 * @copy flash.events.IEventDispatcher#addEventListener()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false): void
+		{
+			_eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
+		}
+
+		/**
+		 * @copy flash.events.IEventDispatcher#dispatchEvent()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function dispatchEvent(event:Event):Boolean
+		{
+			return _eventDispatcher.dispatchEvent(event);
+		}
+		
+		/**
+		 * @copy flash.events.IEventDispatcher#hasEventListener()
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+ 		 
+		public function hasEventListener(type:String):Boolean
+		{
+			return _eventDispatcher.hasEventListener(type);
+		}
+		
+		/**
+		 * @copy flash.events.IEventDispatcher#removeEventListener().
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */						
+		public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false): void
+		{
+			_eventDispatcher.removeEventListener(type, listener, useCapture);
+		}
+
+		/**
+		 * @copy flash.events.IEventDispatcher#willTrigger()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */								
+		public function willTrigger(type:String):Boolean
+		{
+			return _eventDispatcher.willTrigger(type);
+		}
+		
+		// elements which are images or blocks that *may* have children requiring activation or deactivation
+		private var _elemsToUpdate:Array;
+		
+		/** @private */
+		tlf_internal function appendOneElementForUpdate(elem:FlowElement):void
+		{
+			if (_elemsToUpdate == null)
+				_elemsToUpdate = [ elem ];
+			else
+				_elemsToUpdate.push(elem);
+		}
+		
+		/** @private */
+		tlf_internal function mustUseComposer():Boolean
+		{ 
+			if (_elemsToUpdate == null || _elemsToUpdate.length == 0)
+				return false; 
+				
+			normalize();
+			
+			// anything that doesn't normalize completely forces use of the compser
+			var rslt:Boolean = false;
+			for each (var elem:FlowElement in _elemsToUpdate)
+			{
+				if (elem.updateForMustUseComposer(this))
+					rslt = true;
+			}
+			
+			return rslt;
+		}
+		
+		/** @private */
+		tlf_internal function processModelChanged(changeType:String, elem:FlowElement, changeStart:int, changeLen:int, needNormalize:Boolean, bumpGeneration:Boolean):void
+		{
+			// track added and removed elements while the flow is visible
+			if (flowComposer)
+				elem.appendElementsForDelayedUpdate(this);
+			
+			if (bumpGeneration)
+				_generation = _nextGeneration++;
+			
+			if (changeLen > 0)
+				damage(changeStart+elem.getAbsoluteStart(), changeLen, TextLineValidity.INVALID, needNormalize);
+			
+			if (formatResolver)
+			{
+				switch(changeType)
+				{
+					case ModelChange.ELEMENT_REMOVAL:
+					case ModelChange.ELEMENT_ADDED:
+					case ModelChange.STYLE_SELECTOR_CHANGED:
+						formatResolver.invalidate(elem);
+						elem.formatChanged(false);
+						break;
+				}
+			}
+		}
+		
+		/** 
+		* The generation number for this TextFlow object. The undo and redo operations use the generation number to validate that 
+		* it's legal to undo or redo an operation. The generation numbers must match. 
+		* 
+		* <p>Each model change increments <code>generation</code> so if the generation number changes, you know the 
+		* TextFlow model has changed.</p>
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+	 	
+		public function get generation():uint
+		{
+			return _generation;
+		}
+		
+		/** used to reset the number backwards after an undo or redo. @private */
+		tlf_internal function setGeneration(num:uint):void
+		{
+			_generation = num;
+		}
+		
+		/** @private */
+		tlf_internal function processAutoSizeImageLoaded(elem:InlineGraphicElement):void
+		{
+			if (flowComposer)
+				elem.appendElementsForDelayedUpdate(this);
+		}
+		
+		/**
+		 * Examine the damaged textLength of the TextFlow and put it in a normal form.  This includes adding spans to empty paragraph and
+		 * merging sibling spans that have the same attributes.
+		 * @private 
+		 */
+		tlf_internal function normalize():void
+		{
+			//trace("NORMALIZE");
+			
+			if (normalizeStart != -1)
+			{
+				var normalizeEnd:int = normalizeStart + (normalizeLen==0?1:normalizeLen);
+				normalizeRange(normalizeStart,normalizeEnd);
+
+				normalizeStart = -1;
+				normalizeLen = 0;				
+			}
+			CONFIG::debug { debugCheckTextFlow(false); }
+		}
+		
+		private var _hostFormatHelper:HostFormatHelper;
+		
+		/** The TextLayoutFormat object for this TextFlow object. This enables several optimizations for reusing 
+		* host formats. For example;
+		*
+		* <listing>
+		* textFlowA.hostFormat = textFlowB.hostFormat
+		* </listing>
+		* 
+		* You must set format values before assigning the TextLayoutFormat object to <code>hostFormat</code>.
+		* For example, the following lines do <em>not</em> set the font size to 24 because
+		* the font size is set <em>after</em> the TextLayoutFormat object has been assigned to <code>hostFormat</code>.
+		*
+		* <listing>
+		* format = new TextLayoutFormat()
+		* textFlow.hostFormat = format
+		* format.fontSize = 24;
+		* </listing>
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*
+	 	* @see flashx.textLayout.formats.ITextLayoutFormat ITextLayoutFormat
+	 	*/
+	 	
+		public function get hostFormat():ITextLayoutFormat
+		{ return _hostFormatHelper ? _hostFormatHelper.format : null; }
+		public function set hostFormat(value:ITextLayoutFormat):void
+		{
+			if (value == null)
+				_hostFormatHelper = null;
+			else
+			{
+				if (_hostFormatHelper == null)
+					_hostFormatHelper = new HostFormatHelper();
+				_hostFormatHelper.format = value;
+			}
+			formatChanged();
+		}
+		/** @private */
+		tlf_internal function getDefaultFormat():ITextLayoutFormat
+		{
+			if (_hostFormatHelper == null)
+				return TextLayoutFormat.defaultFormat;
+
+			return _hostFormatHelper.computedFormat;
+		}
+		/** @private */
+		tlf_internal function getDefaultFormatHash():uint
+		{
+			// note it calls getDefaultFormat which will force computedFormat to be called and getComputedTextLayoutFormatHash will be valid
+			return getDefaultFormat() == TextLayoutFormat.defaultFormat ? TextLayoutFormat.getDefaultFormatHash() : _hostFormatHelper.getComputedTextLayoutFormatHash();
+		}
+		
+		
+		/** Use the formatResolver to get the character style of an Object.
+		 * @param elem is either a FlowElement or a ContainerController(doesn't happen for characterformat)
+		 * @return any styled CharacterFormat for that element
+		 * @private
+		 */
+		tlf_internal function getTextLayoutFormatStyle(elem:Object):ITextLayoutFormat
+		{
+			return _formatResolver != null ? (_formatResolver.resolveFormat(elem) as ITextLayoutFormat) : null;
+		}
+		
+		/** @private */
+		tlf_internal function set backgroundManager(bgm:BackgroundManager):void
+		{
+			if(_backgroundManager)
+				_backgroundManager.textFlow = null;
+			_backgroundManager = bgm;
+			if(_backgroundManager)
+				_backgroundManager.textFlow = this;
+		}
+		
+		/** @private */
+		tlf_internal function get backgroundManager():BackgroundManager
+		{
+			return _backgroundManager;
+		}
+		
+		/** A callback function for resolving element styles. You can use this to provide styling using CSS or 
+		 * named styles, for example. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see IFormatResolver
+		 */
+		 
+		public function get formatResolver(): IFormatResolver
+		{ 
+			return _formatResolver; 
+		}
+		public function set formatResolver(val:IFormatResolver):void
+		{
+			if (_formatResolver != val)
+			{
+				if (_formatResolver)
+					_formatResolver.invalidateAll(this);
+				_formatResolver = val;
+				if (_formatResolver)
+					_formatResolver.invalidateAll(this);
+					
+				formatChanged(true);
+			}
+		}
+		
+		/** Invalidates all formatting information for the TextFlow, forcing it to be recomputed.
+		 * Call this method when styles have changed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+	 	 * @see IFormatResolver#invalidateAll()
+		 */
+		 
+		public function invalidateAllFormats():void
+		{
+			if (_formatResolver)
+				_formatResolver.invalidateAll(this);
+			if (GlobalSettings.fontMapperFunction != null)
+				FlowLeafElement.clearElementFormatsCache(); // clear out possibly stale mappings between computed TextLayoutFormats and ElementFormats
+			formatChanged(true);
+		}
+		
+		/** @private */
+		static private var _dictionary:Dictionary = new Dictionary();
+		 
+		static private var _seeksSinceLastPurge:int = 0;
+
+		/** @private */
+		CONFIG::debug static tlf_internal var _dictionarySeeks:Number = 0;
+
+		/** @private */
+		CONFIG::debug static tlf_internal var _dictionaryHits:Number = 0;
+
+		/** @private */
+		CONFIG::debug static tlf_internal var _dictionaryCollisions:Number = 0;
+
+		/** @private */		
+		CONFIG::debug static tlf_internal var _emptyRef:int = 0;
+		
+		/** Gets the canonical TextLayoutFormat object that is equal to incoming.
+		 * This class maintains a collection of TextLayoutFormat objects no two of which are functionally equivalent.
+		 * To reduce memory consumption, code elsewhere that intends to hold references to TextLayoutFormat objects
+		 * should refer to these 'canonical' objects -- obtained by calling this method.
+		 * Note: If no TextLayoutFormat object equal to incoming already exists in the collection, a new one is created and added.
+		 * This function never returns null unless incoming is null.
+		 * @param incoming the object whose canonical equivalent is requested
+		 * @param addDefaults whether incoming already includes defaults. If not, defaults will be concatenated before lookup.
+		 * @return the canonical object equal to incoming
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @private
+		 */
+		static tlf_internal function getCanonical(incoming:TextLayoutFormatValueHolder,defaultFormat:ITextLayoutFormat,defaultFormatHash:uint):ITextLayoutFormat
+		{
+			if (defaultFormat == null)
+			{
+				defaultFormat = TextLayoutFormat.defaultFormat;
+				defaultFormatHash = TextLayoutFormat.getDefaultFormatHash();
+			}
+			
+			if (incoming == null)
+				return defaultFormat;
+				
+			CONFIG::debug { _dictionarySeeks++; }
+			
+			_seeksSinceLastPurge++;
+			
+			// The cache dictionary never garbage collects any entries - even though it constructed with weakKeys the keys are uints and so don't get gc'ed
+			// Every 1000 seeks iterate over the values in the dicitionary and delete dictionary entries with garbage collected values
+			// note iteratiing over the keys returns strings which require a string to uint conversion and another lookup.  Storing the keys in the values saves this work.
+			if (_seeksSinceLastPurge == 1000)
+			{
+				for each ( var item:Object in _dictionary )
+				{
+					if (item.format.get() == null)
+						delete _dictionary[item.hash];
+				}
+				_seeksSinceLastPurge = 0;
+			}
+					
+			/*CONFIG::debug
+			{
+				if((_dictionarySeeks % 100) == 0)
+				{
+					var dictLen:int = 0;
+					var emptySlot:int = 0;
+					for each ( item in _dictionary )
+					{
+						if (item.format.get() == null)
+							emptySlot++;
+						dictLen++;
+					}
+
+					trace("TextLayoutFormat.getCanonical Seeks:" + _dictionarySeeks + " Hits:" + _dictionaryHits + " Collisions:" + _dictionaryCollisions + " EmptyRefs:" + _emptyRef + " DictLength:" + dictLen + " EmptySlots:" + emptySlot);
+				}
+			}*/
+			var hash:uint = incoming.hash(defaultFormatHash);
+
+			var cacheObject:Object = _dictionary[hash];
+			if (cacheObject)
+			{
+				var format:TextLayoutFormat = cacheObject.format.get();
+				if (format)
+				{
+					if (defaultFormat == cacheObject.defaultFormat && Property.equalCoreStyles(incoming.coreStyles,cacheObject.coreStyles,TextLayoutFormat.description))
+					{
+						CONFIG::debug {_dictionaryHits++;}				
+						return format;
+					}
+					
+					CONFIG::debug {_dictionaryCollisions++;}	
+				}
+				else
+				{
+					CONFIG::debug { _emptyRef++; }
+				}
+				// Handled below; previous object bumped out
+			}
+			
+			var newFormat:TextLayoutFormat = new TextLayoutFormat(incoming);
+			newFormat.concat(defaultFormat);
+			
+			cacheObject = new Object();
+			cacheObject.coreStyles = Property.shallowCopy(incoming.coreStyles);
+			cacheObject.format = new WeakRef(newFormat);
+			cacheObject.defaultFormat = defaultFormat;
+			cacheObject.hash = hash
+			_dictionary[hash] = cacheObject;
+			
+			/* CONFIG::debug 
+			{
+				for each (var prop:Property in TextLayoutFormat.description)
+				{
+					assert(newFormat[prop.name] !== undefined,"BAD CASCADE");
+				}
+			} */
+
+			return newFormat;
+		}
+	} // end TextFlow class
+}
+import flash.utils.Dictionary;
+
+import flashx.textLayout.debug.assert;
+import flashx.textLayout.formats.TextLayoutFormat;
+import flashx.textLayout.formats.ITextLayoutFormat;
+import flashx.textLayout.tlf_internal;
+
+use namespace tlf_internal;
+
+/** @private.  Expected usage is that all values are set. */
+class HostFormatHelper
+{
+	static private const computedFormatCache:Dictionary = new Dictionary(true);
+
+	private var _format:ITextLayoutFormat;
+	
+	public function get format():ITextLayoutFormat
+	{ return _format; }
+	public function set format(value:ITextLayoutFormat):void
+	{ _format = value; _computedFormat = null; }
+	
+	private var _computedFormat:ITextLayoutFormat;
+	private var _computedFormatHash:uint;
+	
+	public function get computedFormat():ITextLayoutFormat
+	{ 
+		if (_computedFormat)
+			return  _computedFormat;
+				
+		var cacheObject:Object = computedFormatCache[_format];
+
+		if (cacheObject == null)
+		{
+			var format:TextLayoutFormat = new TextLayoutFormat(format);
+			format.concat(TextLayoutFormat.defaultFormat);
+				
+			cacheObject = new Object();
+			cacheObject.format = format;
+			cacheObject.hash = format.hash(0);
+			computedFormatCache[_format] = cacheObject;
+			//trace("Miss");
+		}
+		// else trace("Hit");
+
+		_computedFormat = cacheObject.format;
+		_computedFormatHash = cacheObject.hash;		
+		return _computedFormat;
+	}
+	
+	public function getComputedTextLayoutFormatHash():uint
+	{
+		CONFIG::debug { assert( _computedFormat != null, " bad call to getComputedTextLayoutFormatHash"); }
+		return _computedFormatHash; 
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/elements/TextRange.as b/textLayout_core/src/flashx/textLayout/elements/TextRange.as
new file mode 100755
index 0000000..15eb91b
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/elements/TextRange.as
@@ -0,0 +1,169 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.elements
+{
+	import flashx.textLayout.elements.TextFlow;
+	
+	/**
+	 * A read only class that describes a range of contiguous text. Such a range occurs when you select a
+	 * section of text. The range consists of the anchor point of the selection, <code>anchorPosition</code>,
+	 * and the point that is to be modified by actions, <code>activePosition</code>.  As block selections are 
+	 * modified and extended <code>anchorPosition</code> remains fixed and <code>activePosition</code> is modified.  
+	 * The anchor position may be placed in the text before or after the active position.
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 *
+	 * @see flashx.textLayout.elements.TextFlow TextFlow
+	 * @see flashx.textLayout.edit.SelectionState SelectionState
+	 */
+	public class TextRange
+	{
+		/** The TextFlow of the selection.
+ 	 	 */
+		private var _textFlow:TextFlow;
+		
+		// current range of selection
+		/** Anchor point of the current selection, as an absolute position in the TextFlow. */
+		private var _anchorPosition:int;
+		/** Active end of the current selection, as an absolute position in the TextFlow. */
+		private var _activePosition:int;
+		
+		private function clampToRange(index:int):int
+		{
+			if (index < 0)
+				return 0;
+			if (index > _textFlow.textLength)
+				return _textFlow.textLength;
+			return index;
+		}
+		
+		/** Constructor - creates a new TextRange instance.  A TextRange can be (-1,-1), indicating no range, or a pair of 
+		* values from 0 to <code>TextFlow.textLength</code>.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @param	root	the TextFlow associated with the selection.
+		 * @param anchorIndex	the index position of the anchor in the selection. The first position in the text is position 0.
+		 * @param activeIndex	the index position of the active location in the selection. The first position in the text is position 0. 
+		 *
+		 * @see FlowElement#textLength
+		 */		
+		public function TextRange(root:TextFlow,anchorIndex:int,activeIndex:int)
+		{
+			_textFlow = root;
+			
+			if (anchorIndex != -1 || activeIndex != -1)
+			{
+				anchorIndex = clampToRange(anchorIndex);
+				activeIndex = clampToRange(activeIndex);
+			}
+			
+			_anchorPosition = anchorIndex;
+			_activePosition = activeIndex;
+		}
+		
+		/** Update the range with new anchor or active position values.
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 *  @param newAnchorPosition	the anchor index of the selection.
+		 *  @param newActivePosition	the active index of the selection.
+		 *  @return true if selection is changed.
+		 */
+		public function updateRange(newAnchorPosition:int,newActivePosition:int):Boolean
+		{
+			if (newAnchorPosition != -1 || newActivePosition != -1)
+			{
+				newAnchorPosition = clampToRange(newAnchorPosition);
+				newActivePosition = clampToRange(newActivePosition);
+			}
+			
+			if (_anchorPosition != newAnchorPosition || _activePosition != newActivePosition)
+			{
+				_anchorPosition = newAnchorPosition;
+				_activePosition = newActivePosition;
+				return true;
+			}
+			return false;
+		}
+		
+		/** Returns the TextFlow associated with the selection.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */						
+		public function get textFlow():TextFlow
+		{ return _textFlow; }
+		public function set textFlow(value:TextFlow):void
+		{ _textFlow = value; }
+		
+		/** Anchor position of the selection, as an absolute position in the TextFlow.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */								
+		public function get anchorPosition():int
+		{ return _anchorPosition; }
+		public function set anchorPosition(value:int):void
+		{ _anchorPosition = value; }
+		
+		/** Active position of the selection, as an absolute position in the TextFlow.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */										
+		public function get activePosition():int
+		{ return _activePosition; }
+		public function set activePosition(value:int):void
+		{ _activePosition = value; }
+		
+		/** Start of the selection, as an absolute position in the TextFlow.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */										
+		public function get absoluteStart():int
+		{ return _activePosition < _anchorPosition ? _activePosition : _anchorPosition; }
+		public function set absoluteStart(value:int):void
+		{
+			if (_activePosition < _anchorPosition)
+				_activePosition = value;
+			else
+				_anchorPosition = value;
+		}
+		
+		/** End of the selection, as an absolute position in the TextFlow.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */								
+		public function get absoluteEnd():int
+		{ return _activePosition > _anchorPosition ? _activePosition : _anchorPosition; }
+		public function set absoluteEnd(value:int):void
+		{
+			if (_activePosition > _anchorPosition)
+				_activePosition = value;
+			else
+				_anchorPosition = value;
+		}		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/events/CompositionCompleteEvent.as b/textLayout_core/src/flashx/textLayout/events/CompositionCompleteEvent.as
new file mode 100755
index 0000000..e4332a5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/CompositionCompleteEvent.as
@@ -0,0 +1,127 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	import flashx.textLayout.elements.TextFlow;
+	
+	/** 
+	 * A TextFlow instance dispatches this event after a compose operation completes. 
+	 * Each text container has two states: composition and display. This event notifies
+	 * you when the composition phase has ended. This provides an opportunity to make any
+	 * necessary and appropriate changes to the container before you display the text. 
+	 * For example, you can use this event to add highlighting of certain words or
+	 * characters in the text flow before the text is displayed.
+	 * 
+	 * <p>The three main methods that dispatch this event are <code>compose()</code>, 
+	 * <code>updateToController()</code>, and <code>updateAllControllers()</code>.
+	 * All three of these methods are in the StandardFlowComposer class.</p>
+	 *
+	 * <p><strong>Note: </strong>If the event is dispatched by the
+	 * <code>updateAllControllers()</code> method, do not call 
+	 * <code>updateAllControllers()</code> again in your event handler function.
+	 * Such a call would be a recursive call because the <code>updateAllControllers()</code> 
+	 * method executes both the composition and display steps. The <code>updateAllControllers()</code>
+	 * dispatches this event after composition completes, but before the display step executes.
+	 * The same reasoning applies to the <code>updateToController()</code> method.
+	 * </p>
+	 *
+	 * @includeExample examples\CompositionCompleteEvent_example.as -noswf
+	 *
+	 * @see flashx.textLayout.elements.TextFlow 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class CompositionCompleteEvent extends Event
+	{
+	    /** 
+	     * Defines the value of the <code>type</code> property of a <code>compositionComplete</code> event object 
+	     * @playerversion Flash 10
+	     * @playerversion AIR 1.5
+	     * @langversion 3.0 
+	     */
+	    public static const COMPOSITION_COMPLETE:String = "compositionComplete";
+		
+		
+		//temporary removal of params until Flex removes references to old CompositionCompletionEvent
+		private var _compositionStart:int;
+		private var _compositionLength:int;
+		private var _textFlow:TextFlow;	
+		
+		/** Constructor
+		 * @param type event type - use the static property COMPOSITION_COMPLETE.
+		 * @param bubbles Indicates whether an event is a bubbling event. This event does not bubble.
+		 * @param cancelable Indicates whether the behavior associated with the event can be prevented.
+		 * This event cannot be cancelled.
+		 * @param textFlow The TextFlow which was composed
+		 * @param compositionStart start of composition, in terms of an index into the text flow.
+		 * @param compositionLength length number of characters composed
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 **/
+		public function CompositionCompleteEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, textFlow:TextFlow =  null, compositionStart:int=0, compositionLength:int=0)
+		{
+			_compositionStart = compositionStart;
+			_compositionLength = compositionLength;
+			_textFlow = textFlow
+			super(type, bubbles, cancelable);
+		}
+		
+      	/** @private */
+		override public function clone():Event
+		{
+			return new CompositionCompleteEvent(type, bubbles, cancelable, textFlow, compositionStart, compositionLength);
+		}
+		
+		/** 
+		 * The start location of the text range affected by the composition, expressed as an index into the text flow.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 		 
+		 */
+		public function get compositionStart():int
+		{ return _compositionStart; }		
+		public function set compositionStart(value:int):void
+		{ _compositionStart = value; }		
+		
+		/** 
+		 * The number of characters composed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get compositionLength():int
+		{ return _compositionLength; }
+		public function set compositionLength(value:int):void
+		{ _compositionLength = value; }
+		
+		/**
+		 * TextFlow on which composition has been completed. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textFlow():TextFlow
+		{ return _textFlow; }
+		public function set textFlow(value:TextFlow):void
+		{ _textFlow = value; }
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/events/DamageEvent.as b/textLayout_core/src/flashx/textLayout/events/DamageEvent.as
new file mode 100755
index 0000000..d371fa5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/DamageEvent.as
@@ -0,0 +1,97 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.TextFlow;
+	
+	/** 
+	 * A TextFlow instance dispatches this each time it is marked as damaged.  Damage can be caused by changes to the model or changes to the layout.
+	 * 
+	 * @includeExample examples\DamageEvent_example.as -noswf
+	 * 
+	 * @see flashx.textLayout.elements.TextFlow 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class DamageEvent extends Event
+	{
+		/** Event type for DamageEvent */
+	    public static const DAMAGE:String = "damage";
+
+		private var _textFlow:TextFlow;
+		private var _damageAbsoluteStart:int;
+		private var _damageLength:int;	
+		
+		/** Constructor
+		 * @param damageAbsoluteStart text index of the start of the damage
+		 * @param damageLength length of text that was damaged
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function DamageEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, textFlow:TextFlow =  null, damageAbsoluteStart:int = 0, damageLength:int = 0)
+		{
+			_textFlow = textFlow;
+			_damageAbsoluteStart = damageAbsoluteStart;
+			_damageLength = damageLength;
+			super(type, bubbles, cancelable);
+		}
+		
+      	/** @private */
+		override public function clone():Event
+		{
+			return new DamageEvent(type, bubbles, cancelable, _textFlow, _damageAbsoluteStart, _damageLength);
+		}
+		
+		/**
+		 * TextFlow owning the damage 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		public function get textFlow():TextFlow
+		{ return _textFlow; }
+		
+		/**
+		 * Absolute start of the damage 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		public function get damageAbsoluteStart():int
+		{ return _damageAbsoluteStart; }
+		
+		/**
+		 * Length of the damage 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+
+		public function get damageLength():int
+		{ return _damageLength; }
+	}
+}
+
diff --git a/textLayout_core/src/flashx/textLayout/events/FlowElementMouseEvent.as b/textLayout_core/src/flashx/textLayout/events/FlowElementMouseEvent.as
new file mode 100755
index 0000000..abc53f3
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/FlowElementMouseEvent.as
@@ -0,0 +1,160 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	import flash.events.MouseEvent;
+	import flashx.textLayout.elements.FlowElement;
+			
+	/** A LinkElement dispatches this event when it detects mouse activity.
+	 * The Text Layout Framework includes this special version of mouse events
+	 * because mouse events are generally unwanted when a link element is
+	 * embedded in an editable text flow. 
+	 * <p>You can add an event listener to a LinkElement to listen for this
+	 * type of event. If you choose to cancel the event by calling
+	 * <code>Event.preventDefault()</code>, the default behavior associated
+	 * with the event will not occur.
+	 * </p>
+	 * <p>If you choose not to add an event listener to the LinkElement, or
+	 * your event listener function does not cancel the behavior, the 
+	 * event is again dispatched, but this time by the LinkElement's
+	 * associated TextFlow instance rather than by the LinkElement itself. 
+	 * This provides a second opportunity to listen for this event with
+	 * an event listener attached to the TextFlow. 
+	 * </p>
+	 * <p>FlowElementMouseEvents are
+	 * dispatched only when the text cannot be edited or when the control key 
+	 * is pressed concurrently with the mouse activity.</p>
+	 * <p>
+	 * The following six event types are dispatched only when the text
+	 * cannot be edited or when the control key is pressed:
+	 * <ul>
+	 *   <li><code>MouseEvent.CLICK</code></li>
+	 *   <li><code>MouseEvent.MOUSE_DOWN</code></li>
+	 *   <li><code>MouseEvent.MOUSE_OUT</code></li>
+	 *   <li><code>MouseEvent.MOUSE_UP</code></li>
+	 *   <li><code>MouseEvent.ROLL_OVER</code></li>
+	 *   <li><code>MouseEvent.ROLL_OUT</code></li>
+	 * </ul>
+	 * </p>
+	 *
+	 * @includeExample examples\FlowElementMouseEvent_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * @see flashx.textLayout.elements.LinkElement
+	 */
+	public class FlowElementMouseEvent extends Event
+	{
+		
+		public static const MOUSE_DOWN:String = "mouseDown";
+		public static const MOUSE_UP:String = "mouseUp";	
+		public static const MOUSE_MOVE:String = "mouseMove";			
+		public static const ROLL_OVER:String = "rollOver";
+		public static const ROLL_OUT:String = "rollOut";	
+		public static const CLICK:String = "click";
+
+		private var _flowElement:FlowElement;
+		private var _originalEvent:MouseEvent;
+		
+		/** 
+		 * The LinkElement that dispatched the event.
+		 *
+		 * @see flashx.textLayout.elements.LinkElement
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get flowElement():FlowElement
+		{ return _flowElement; }		
+		public function set flowElement(value:FlowElement):void
+		{ _flowElement = value; }
+		
+		/** 
+		 * The original mouse event generated by the mouse activity. 
+		 * This property can contain any of the following values:
+		 * <ul>
+		 *   <li><code>MouseEvent.CLICK</code></li>
+		 *   <li><code>MouseEvent.MOUSE_DOWN</code></li>
+		 *   <li><code>MouseEvent.MOUSE_OUT</code></li>
+		 *   <li><code>MouseEvent.MOUSE_UP</code></li>
+		 *   <li><code>MouseEvent.MOUSE_OVER</code></li>
+		 *   <li><code>MouseEvent.MOUSE_OUT</code></li>
+		 * </ul>
+		 * <p>
+		 * In most cases the original event matches the event that the
+		 * LinkElement dispatches. The events match for the <code>click</code>,
+		 * <code>mouseDown</code>, <code>mouseOut</code>, and <code>mouseOver</code>
+		 * events. There are two cases, however, in which the original event
+		 * is converted by the LinkElement to a related event. 
+		 * If a LinkElement detects a <code>mouseOver</code> event, it dispatches
+		 * a <code>rollOver</code> event. Likewise, if a LinkElement detects
+		 * a <code>mouseOut</code> event, it dispatches a <code>rollOut</code> event.
+		 * </p>
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 * @see flash.events.MouseEvent
+		 */
+		public function get originalEvent():MouseEvent
+		{ return _originalEvent; }		
+		public function set originalEvent(value:MouseEvent):void
+		{ _originalEvent = value; }
+				
+		/** 
+		 * Creates an event object that contains information about mouse activity.
+		 * Event objects are passed as parameters to event listeners. Use the
+		 * constructor if you plan to manually dispatch an event. You do not need
+		 * to use the constructor to listen for FlowElementMouseEvent objects
+		 * generated by a LinkElement.
+		 * @param type  The type of the event. Event listeners can access this information through the
+		 * inherited <code>type</code> property. There are six types:
+		 * <code>MouseEvent.CLICK</code>; <code>MouseEvent.MOUSE_DOWN</code>; <code>MouseEvent.MOUSE_OUT</code>;
+		 * <code>MouseEvent.MOUSE_UP</code>; <code>MouseEvent.ROLL_OVER</code>; and <code>MouseEvent.ROLL_OUT</code>.
+		 * @param bubbles Determines whether the Event object participates in the bubbling phase of the
+		 * event flow. FlowElementMouseEvent objects do not bubble.
+		 * @param cancelable Determines whether the Event object can be canceled. Event listeners can
+		 * access this information through the inherited <code>cancelable</code> property. FlowElementMouseEvent
+		 * objects can be cancelled. You can cancel the default behavior associated with this event
+		 * by calling the <code>preventDefault()</code> method in your event listener.
+		 * @param flowElement The instance of FlowElement, usually a LinkElement, associated with this
+		 * event. Event listeners can access this information through the <code>flowElement</code> property.
+		 * @param originalEvent The original mouse event that occurred on the flowElement. Event listeners can 
+		 * access this information through the <code>originalEvent</code> property.
+
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function FlowElementMouseEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = true, flowElement:FlowElement = null, originalEvent:MouseEvent = null)
+		{
+			super(type, bubbles, cancelable);
+			_flowElement = flowElement;
+			_originalEvent = originalEvent;
+        }
+        
+        /** @private */
+        override public function clone():Event
+        {
+        	return new FlowElementMouseEvent(type, bubbles, cancelable, flowElement, originalEvent);
+        }
+        
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/events/ModelChange.as b/textLayout_core/src/flashx/textLayout/events/ModelChange.as
new file mode 100755
index 0000000..cc23230
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/ModelChange.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.events
+{
+	
+	/** ModelChange values.  These are various types of model change. @private */
+	public final class ModelChange
+	{
+		public static const ELEMENT_ADDED:String    = "elementAdded";
+		public static const ELEMENT_REMOVAL:String  = "elementRemoval";
+		public static const ELEMENT_MODIFIED:String = "elementModified";		
+		
+		public static const TEXTLAYOUT_FORMAT_CHANGED:String = "formatChanged";
+		
+		public static const TEXT_INSERTED:String = "textInserted";
+		public static const TEXT_DELETED:String  = "textDeleted";
+		
+		public static const STYLE_SELECTOR_CHANGED:String = "styleSelectorChanged";
+		
+		public static const USER_STYLE_CHANGED:String = "userStyleChanged";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/events/StatusChangeEvent.as b/textLayout_core/src/flashx/textLayout/events/StatusChangeEvent.as
new file mode 100755
index 0000000..4b1153a
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/StatusChangeEvent.as
@@ -0,0 +1,125 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.ErrorEvent;
+	import flash.events.Event;
+	
+	import flashx.textLayout.elements.FlowElement;
+	
+	/** 
+	 * A TextFlow instance dispatches this event when the status of a FlowElement changes. 
+	 * This event can be used to detect when an inline graphic element has
+	 * completed loading. You can use your event handler to recompose the text flow
+	 * based on the presence of the newly loaded inline graphic element.
+	 *
+	 * @includeExample examples\StatusChangeEvent_example.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class StatusChangeEvent extends Event
+	{
+	    /** 
+	     * Defines the value of the <code>type</code> property of a <code>inlineGraphicStatusChanged</code> event object.
+	     * @playerversion Flash 10
+	     * @playerversion AIR 1.5
+	     * @langversion 3.0 
+	     */
+	    public static const INLINE_GRAPHIC_STATUS_CHANGE:String = "inlineGraphicStatusChange";
+	    
+	    private var _element:FlowElement;
+	    private var _status:String;
+	    private var _errorEvent:ErrorEvent;
+
+		/** Creates an event object that contains information about a status change.
+		 * @param type		The type of the event. Event listeners can access this information through the
+		 * inherited <code>type</code> property. There is only one type of StatusChangeEvent: 
+		 * <code>StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE</code>; 
+		 * @param bubbles 	Indicates whether an event is a bubbling event.This event does not bubble.
+		 * @param cancelable 	Indicates whether the behavior associated with the event can be prevented.
+		 * This event cannot be cancelled.
+		 * @param element The FlowElement instance that has experienced a change in status.
+		 * @param newStatus The FlowElement instance's new status.
+		 * @param e The ErrorEvent object, if any, associated with the status.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 **/
+		public function StatusChangeEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, element:FlowElement = null,status:String = null,errorEvent:ErrorEvent = null)
+		{
+			_element = element;
+			_status = status;
+			_errorEvent = errorEvent;
+			super(type, false, false);
+		}
+		
+      	/** @private */
+		override public function clone():Event
+		{
+			return new StatusChangeEvent(type,bubbles,cancelable,_element,_status,_errorEvent);
+		}
+		
+		/** 
+		 * The FlowElement instance that has experienced a change in status. 
+		 * @see flashx.textLayout.elements.FlowElement
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get element():FlowElement
+		{ return _element; }		
+		public function set element(value:FlowElement):void
+		{ _element = value; }		
+		
+		/**
+		 * The FlowElement's new status. The possible values of this property are
+		 * defined by the InlineGraphicElementStatus class. There are five static constants
+		 * available in the InlineGraphicElementStatus class:
+		 * <ul>
+		 *   <li>ERROR : String = "error". An error occurred during loading of a referenced graphic.</li>
+		 *   <li>LOADING : String = "loading". Load has been initiated (but not completed) on a graphic element that is a URL.</li>
+		 *   <li>LOAD_PENDING : String = "loadPending". Graphic element is an URL that has not been loaded.</li>
+		 *   <li>READY : String = "ready". Graphic is completely loaded and properly sized.</li>
+		 *   <li>SIZE_PENDING : String = "sizePending". Graphic element with auto or percentage width/height has completed loading but has not been recomposed.</li>
+		 * </ul>
+		 *
+		 * @see flashx.textLayout.elements.InlineGraphicElementStatus
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get status():String
+		{ return _status; }
+		public function set status(value:String):void
+		{ _status = value; }
+		
+		/** 
+		 * The ErrorEvent object that was dispatched as a result of the status change. 
+		 * @see flash.events.ErrorEvent
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get errorEvent():ErrorEvent
+		{ return _errorEvent; }
+		public function set errorEvent(value:ErrorEvent):void
+		{ _errorEvent = value; }
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/events/TextLayoutEvent.as b/textLayout_core/src/flashx/textLayout/events/TextLayoutEvent.as
new file mode 100755
index 0000000..56f751c
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/TextLayoutEvent.as
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	
+	/**
+	 * A TextLayoutEvent instance represents an event, such as the 
+	 * <code>TextLayoutEvent.SCROLL</code> event, that does not require
+	 * custom properties. 
+	 * <p>A scroll event is represented by a TextLayoutEvent instance with its 
+	 * <code>type</code> property set to <code>TextLayoutEvent.SCROLL</code>.
+	 * A class specifically for scroll events is not necessary because there are
+	 * no custom properties for a scroll event, as there are for the other
+	 * events that have specific event classes.
+	 * If a new text layout event is needed, and the event does not require
+	 * custom properties, the new event will also be represented by a
+	 * TextLayoutEvent object, but with its <code>type</code> property
+	 * set to a new static constant.
+	 * </p>
+	 *
+	 * @includeExample examples\TextLayoutEvent_example.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class TextLayoutEvent extends Event
+	{
+	    /**
+	     *  The <code>TextLayoutEvent.SCROLL</code> constant defines the value of the
+	     *  <code>type</code> property of the event object for a <code>scroll</code> event.
+	     * @playerversion Flash 10
+	     * @playerversion AIR 1.5
+	     * @langversion 3.0
+	     */
+	    public static const SCROLL:String = "scroll";
+	    
+		/**
+		 *  The TextLayoutEvent class represents the event object passed to
+		 *  the event listener for many Text Layout events.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TextLayoutEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
+		{
+			super(type, bubbles, cancelable);
+		}
+		
+        /** @private */
+        override public function clone():Event
+        {
+        	return new TextLayoutEvent(type, bubbles, cancelable);
+        }		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/events/UpdateCompleteEvent.as b/textLayout_core/src/flashx/textLayout/events/UpdateCompleteEvent.as
new file mode 100755
index 0000000..f3f082c
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/events/UpdateCompleteEvent.as
@@ -0,0 +1,106 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.TextFlow;
+
+	/** 
+	 * A TextFlow instance dispatches this event after any of its containers completes 
+	 * an update. Each text container has two states: composition and display. This 
+	 * event notifies you when the display phase has ended. This provides an 
+	 * opportunity to make any necessary changes to the container when it is ready to
+	 * be displayed, but hasn't yet been painted to the screen.
+	 * 
+	 * @internal Note: the DamageEvent_example class contains a good example of 
+	 * using the UpdateCompleteEvent, so I have included it as the class example
+	 * instead of creating a new example. I've updated the description of the
+	 * DamageEvent_example file to include prominent mention of the UpdateCompleteEvent.
+	 *
+	 * @includeExample examples\DamageEvent_example.as -noswf
+	 * @see flashx.textLayout.elements.TextFlow 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class UpdateCompleteEvent extends Event
+	{
+	    /** 
+	     * Defines the value of the <code>type</code> property of an <code>UpdateCompleteEvent</code> object 
+	     * @playerversion Flash 10
+	     * @playerversion AIR 1.5
+	     * @langversion 3.0 
+	     */
+	    public static const UPDATE_COMPLETE:String = "updateComplete";
+	    
+	    /** @private */
+	    private var _controller:ContainerController;
+	    /** @private */
+		private var _textFlow:TextFlow;
+		
+		/** Constructor
+		 * @param type event type - use the static property UPDATE_COMPLETE.
+		 * @param bubbles Indicates whether an event is a bubbling event. This event does not bubble.
+		 * @param cancelable Indicates whether the behavior associated with the event can be prevented.
+		 * This event cannot be cancelled.
+		 * @param controller The ContainerController whose container was updated
+		 * @param textFlow The TextFlow which was updated
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 **/
+		public function UpdateCompleteEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, textFlow:TextFlow =  null, controller:ContainerController=null)
+		{
+			super(type, bubbles, cancelable);
+			this.controller = controller;
+			_textFlow = textFlow;
+		}
+
+      	/** @private */
+		override public function clone():Event
+		{
+			return new UpdateCompleteEvent(type, bubbles, cancelable, _textFlow, _controller);
+		}
+
+		/** 
+		 * The controller of the container being updated
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 		 
+		 */
+		public function get controller():ContainerController
+		{ return _controller; }
+		public function set controller(c:ContainerController):void
+		{ _controller = c; }
+		
+		
+		/**
+		 * TextFlow which has been updated. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public  function get textFlow():TextFlow
+		{ return _textFlow; }
+		public  function set textFlow(value:TextFlow):void
+		{ _textFlow = value; }
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/external/WeakRef.as b/textLayout_core/src/flashx/textLayout/external/WeakRef.as
new file mode 100755
index 0000000..ee292f7
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/external/WeakRef.as
@@ -0,0 +1,66 @@
+/**
+ * Weak reference to an object
+ * 
+ * To create:
+ * var weak:Weakref = new WeakRef( obj );
+ *
+ * To use:
+ * var strong = weak.get();
+ * if( strong != null )
+ * {
+ *     // use strong here
+ * }
+ * else
+ * {
+ *     // garbage collector has disposed of the object
+ * }
+ * 
+ * Author: Richard Lord
+ * Copyright (c) Big Room Ventures Ltd. 2007
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package flashx.textLayout.external
+{
+	import flash.utils.Dictionary;
+	
+[ExcludeClass]
+	/** @private */
+	public class WeakRef
+	{
+		private var dic:Dictionary;
+		
+		public function WeakRef( obj:* )
+		{
+			dic = new Dictionary( true );
+			if (obj != null)
+				dic[obj] = 1;
+		}
+		
+		public function get():*
+		{
+			for( var item:* in dic )
+			{
+				return item;
+			}
+			return null;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/factory/StringTextLineFactory.as b/textLayout_core/src/flashx/textLayout/factory/StringTextLineFactory.as
new file mode 100755
index 0000000..c5c765f
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/factory/StringTextLineFactory.as
@@ -0,0 +1,449 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.factory
+{
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.compose.FlowComposerBase;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+/**
+ * The StringTextLineFactory class provides a simple way to create TextLines from a string. 
+ * 
+ * <p>The text lines are static and are created using a single format and a single paragraph. 
+ * The lines are created to fit in the specified bounding rectangle.</p>
+ * 
+ * <p>The StringTextLineFactory provides an efficient way to create TextLines, since it reuses single TextFlow,
+ * ParagraphElement, SpanElement, and ContainerController objects across many repeated invocations. You can create a
+ * single factory, and use it again and again. You can also reuse all the parts that are the same each time
+ * you call it; for instance, you can reuse the various formats and the bounds.</p> 
+ *
+ * <p><b>Note:</b> To create static lines that use multiple formats or paragraphs, or that include
+ * inline graphics, use a TextFlowTextLineFactory and a TextFlow object. </p>
+ * 
+ * @includeExample examples\StringTextLineFactory_example.as -noswf
+ * 
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see flashx.textLayout.factory.TextFlowTextLineFactory TextFlowTextLineFactory
+*/
+	public final class StringTextLineFactory extends TextLineFactoryBase
+	{
+		private var _tf:TextFlow;
+		private var _para:ParagraphElement;
+		private var _span:SpanElement;
+		private var _formatsChanged:Boolean;
+
+		static private var _defaultConfiguration:Configuration = null;
+		
+		private var _configuration:IConfiguration;
+		
+		/** 
+		 * The configuration used by the internal TextFlow object.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get configuration():IConfiguration
+		{
+			return _configuration; 
+		}
+		
+		/** 
+		 * The default configuration used by this factory if none is specified. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function get defaultConfiguration():IConfiguration
+		{
+			if (!_defaultConfiguration)
+			{
+				_defaultConfiguration = TextFlow.defaultConfiguration.clone();
+				_defaultConfiguration.flowComposerClass = getDefaultFlowComposerClass();
+				_defaultConfiguration.textFlowInitialFormat = null;
+			}
+			return _defaultConfiguration;
+		}
+		
+		/** 
+		 * Creates a StringTextLineFactory object.  
+		 * 
+		 * @param configuration The configuration object used to set the properties of the 
+		 * internal TextFlow object used to compose lines produced by this factory. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function StringTextLineFactory(configuration:IConfiguration = null):void
+		{
+			super();
+			initialize(configuration);
+		}
+		
+		private function initialize(config:IConfiguration):void
+		{	
+			_configuration = Configuration(config ? config : defaultConfiguration).getImmutableClone();
+			_tf = new TextFlow(_configuration);
+			_para = new ParagraphElement();
+			_span = new SpanElement();
+			_para.replaceChildren(0, 0, _span);
+			_tf.replaceChildren(0, 0, _para);
+			
+			_tf.flowComposer.addController(containerController);
+			_formatsChanged = true;
+		}
+		
+		/** 
+		 * The character format. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get spanFormat():ITextLayoutFormat
+		{
+			return _span.format;
+		}
+		public function set spanFormat(format:ITextLayoutFormat):void
+		{
+			_span.format = format;
+			_formatsChanged = true;
+		}
+		/** 
+		 * The paragraph format. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphFormat():ITextLayoutFormat
+		{
+			return _para.format;
+		}
+		public function set paragraphFormat(format:ITextLayoutFormat):void
+		{
+			_para.format = format;
+			_formatsChanged = true;
+		}
+		
+		/** 
+		 * The text flow format.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textFlowFormat():ITextLayoutFormat
+		{
+			return _tf.format;
+		}
+		public function set textFlowFormat(format:ITextLayoutFormat):void
+		{
+			_tf.format = format;
+			_formatsChanged = true;
+		}
+		
+		/** 
+		 * The text to convert into TextLine objects.
+		 * 
+		 * <p>To produce TextLines, call <code>createTextLines()</code> after setting this
+		 * <code>text</code> property and the desired formats.</p> 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get text():String
+		{ return _span.text; }
+		public function set text(string:String):void
+		{
+			_span.text = string;
+		}
+		
+		/** @private  Used for measuring the truncation indicator */
+		static private var _measurementFactory:StringTextLineFactory = null;
+		static private function measurementFactory():StringTextLineFactory
+		{
+			if (_measurementFactory == null)
+				_measurementFactory = new StringTextLineFactory();
+			return _measurementFactory;
+		}
+		static private var _measurementLines:Array = null;
+		static private function measurementLines():Array
+		{
+			if (_measurementLines == null)
+				_measurementLines = new Array();
+			return _measurementLines;
+		}
+		
+		/** 
+		 * Creates TextLine objects using the text currently assigned to this factory object.
+		 * 
+		 * <p>The text lines are created using the currently assigned text and formats and
+		 * are composed to fit the bounds assigned to the <code>compositionBounds</code> property.
+		 * As each line is created, the factory calls the function specified in the 
+		 * <code>callback</code> parameter. This function is passed the TextLine object and
+		 * is responsible for displaying the line.</p>
+		 * 
+		 * <p>To create a different set of lines, change any properties desired and call
+		 * <code>createTextLines()</code> again.</p>
+		 *  
+		 * @param callback	The callback function called for each TextLine object created.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function createTextLines(callback:Function):void
+		{
+			createTextLinesInternal(callback);
+			_factoryComposer._lines.splice(0);
+			if (_pass0Lines)
+				_pass0Lines.splice(0);
+		}
+		
+		/** Internal version preserves generated lines
+		 */
+		private function createTextLinesInternal(callback:Function):void
+		{
+			var measureWidth:Boolean  = !compositionBounds || isNaN(compositionBounds.width);
+			var measureHeight:Boolean = !compositionBounds || isNaN(compositionBounds.height);
+
+			CONFIG::debug { assert(_tf.flowComposer.numControllers == 1,"DisplayController bad number containers"); }
+			CONFIG::debug { assert(containerController == _tf.flowComposer.getControllerAt(0),"ContainerController mixup"); }
+			var bp:String = _tf.computedFormat.blockProgression;
+
+			containerController.setCompositionSize(compositionBounds.width, compositionBounds.height);
+			// override scroll policy if truncation options are set
+			containerController.verticalScrollPolicy = truncationOptions ? ScrollPolicy.OFF : verticalScrollPolicy;
+			containerController.horizontalScrollPolicy = truncationOptions ? ScrollPolicy.OFF : horizontalScrollPolicy;
+
+			_isTruncated = false;
+			_truncatedText = text;
+			
+			if (!_formatsChanged && FlowComposerBase.computeBaseSWFContext(_tf.flowComposer.swfContext) != FlowComposerBase.computeBaseSWFContext(swfContext))
+				_formatsChanged = true;
+
+			_tf.flowComposer.swfContext = swfContext;
+			
+			if (_formatsChanged)
+			{
+				_tf.normalize();
+				_formatsChanged = false;
+			}
+
+			_tf.flowComposer.compose();
+			
+			// Need truncation if all the following are true
+			// - truncation options exist
+			// - content doesn't fit		
+			if (truncationOptions && !doesComposedTextFit(truncationOptions.lineCountLimit, _tf.textLength, bp))
+			{
+				_isTruncated = true;
+				var somethingFit:Boolean = false; // were we able to fit something?
+				var originalText:String = _span.text;
+				
+				computeLastAllowedLineIndex (truncationOptions.lineCountLimit);	
+				if (_truncationLineIndex >= 0)
+				{
+					// Estimate the initial truncation position using the following steps 
+					
+					// 1. Measure the space that the truncation indicator will take
+					measureTruncationIndicator (compositionBounds, truncationOptions.truncationIndicator);
+					
+					// 2. Move target line for truncation higher by as many lines as the number of full lines taken by the truncation indicator
+					_truncationLineIndex -= (_measurementLines.length -1);
+					if (_truncationLineIndex >= 0)
+					{
+						var truncateAtCharPosition:int;
+						
+						if (_tf.computedFormat.lineBreak == LineBreak.EXPLICIT || (bp == BlockProgression.TB ? measureWidth : measureHeight))
+						{
+							// 3., 4. Initial truncation position: end of the last allowed line 
+							var line:TextLine = _factoryComposer._lines[_truncationLineIndex] as TextLine; 
+							truncateAtCharPosition =  line.userData + line.rawTextLength;
+						}
+						else
+						{
+							// 3. Calculate allowed width (width left over from the last line of the truncation indicator)
+							var targetWidth:Number = (bp == BlockProgression.TB ? compositionBounds.width : compositionBounds.height); 
+							if (paragraphFormat)
+							{
+								targetWidth -= (Number(paragraphFormat.paragraphSpaceAfter) + Number(paragraphFormat.paragraphSpaceBefore));
+								if (_truncationLineIndex == 0)
+									targetWidth -= paragraphFormat.textIndent;
+							}
+							
+							var allowedWidth:Number = targetWidth - (_measurementLines[_measurementLines.length-1] as TextLine).unjustifiedTextWidth;
+													
+							// 4. Get the initial truncation position on the target line given this allowed width 
+							truncateAtCharPosition = getTruncationPosition(_factoryComposer._lines[_truncationLineIndex], allowedWidth);
+						}
+						
+						// Save off the original lines: used in getNextTruncationPosition
+						if (!_pass0Lines)
+							_pass0Lines = new Array();
+						_pass0Lines = _factoryComposer.swapLines(_pass0Lines);
+						
+						// Note that for the original lines to be valid when used, the containing text block should not be modified
+						// Cloning the paragraph ensures this 
+						_para = _para.deepCopy() as ParagraphElement; 
+						_span = _para.getChildAt(0) as SpanElement;
+						_tf.replaceChildren(0, 1, _para);
+						_tf.normalize();
+						
+						// Replace all content starting at the inital truncation position with the truncation indicator
+						_span.replaceText(truncateAtCharPosition, _span.textLength, truncationOptions.truncationIndicator);
+						
+						// The following loop executes repeatedly composing text until it fits
+						// In each iteration, an atoms's worth of characters of original content is dropped
+						do
+						{
+							_tf.flowComposer.compose();
+							
+							if (doesComposedTextFit(truncationOptions.lineCountLimit, _tf.textLength, bp))
+							{
+								somethingFit = true;
+								break; 
+							}		
+							
+							if (truncateAtCharPosition == 0)
+								break; // no original content left to make room for truncation indicator
+							
+							// Try again by truncating at the beginning of the preceding atom
+							var newTruncateAtCharPosition:int = getNextTruncationPosition(truncateAtCharPosition);
+							_span.replaceText(newTruncateAtCharPosition, truncateAtCharPosition, null);
+							truncateAtCharPosition = newTruncateAtCharPosition;
+							
+						} while (true);
+					}
+					_measurementLines.splice(0);	// cleanup
+				}
+				
+				if (somethingFit)
+					_truncatedText = _span.text;
+				else
+				{
+					_truncatedText = "";
+					_factoryComposer._lines.splice(0); // return no lines
+				}
+				
+				 _span.text = originalText;
+			}
+			
+			var xadjust:Number = compositionBounds.x;
+			// toptobottom sets zero to the right edge - adjust the locations
+			var controllerBounds:Rectangle = containerController.getContentBounds();
+			if (bp == BlockProgression.RL)
+				xadjust += (measureWidth ? controllerBounds.width : compositionBounds.width);
+				
+			// apply x and y adjustment to the bounds
+			controllerBounds.left += xadjust;
+			controllerBounds.right += xadjust;
+			controllerBounds.top += compositionBounds.y;
+			controllerBounds.bottom += compositionBounds.y;			
+
+			callbackWithTextLines(callback,xadjust,compositionBounds.y);
+
+			setContentBounds(controllerBounds);
+		}
+		
+		
+		/** @private 
+		 * Gets the text that is composed in the preceding call to <code>createTextLines</code>
+		 * If no truncation is performed, a string equal to <code>text</code> is returned. 
+		 * If truncation is performed, but nothing fits, an empty string is returned.
+		 * Otherwise, a substring of <code>text</code> followed by the truncation indicator is returned. 
+		 */
+		tlf_internal function get truncatedText():String
+		{ return _truncatedText; }
+		private var _truncatedText:String;
+		
+		/** 
+		 * Measures the truncation indicator using the same bounds and formats, but without truncation options
+		 * Resultant lines are added to _measurementLines
+		 */
+		private function measureTruncationIndicator (compositionBounds:Rectangle, truncationIndicator:String):void
+		{
+			var originalLines:Array = _factoryComposer.swapLines(measurementLines()); // ensure we don't overwrite original lines
+			var measureFactory:StringTextLineFactory = measurementFactory();
+			measureFactory.compositionBounds = compositionBounds;
+			measureFactory.text = truncationIndicator;
+			measureFactory.spanFormat = spanFormat;
+			measureFactory.paragraphFormat = paragraphFormat;
+			measureFactory.textFlowFormat = textFlowFormat;
+			measureFactory.truncationOptions = null;
+			measureFactory.createTextLinesInternal(noOpCallback);
+			_factoryComposer.swapLines(originalLines); // restore
+		}
+		
+
+		/** 
+		 * Gets the truncation position on a line given the allowed width 
+		 * - Must be at an atom boundary
+		 * - Must scan the line for atoms in logical order, not physical position order
+		 * For example, given bi-di text ABאבCD
+		 * atoms must be scanned in this order 
+		 * A, B, א
+         * ג, C, D  
+		 */
+		private function getTruncationPosition (line:TextLine, allowedWidth:Number):uint
+		{			
+			var consumedWidth:Number = 0;
+			var charPosition:int = line.userData; 						// start of line
+			
+			while (charPosition < line.userData + line.rawTextLength)	// end of line
+			{
+				var atomIndex:int = line.getAtomIndexAtCharIndex(charPosition);
+				var atomBounds:Rectangle = line.getAtomBounds(atomIndex); 
+				consumedWidth += atomBounds.width;
+				if (consumedWidth > allowedWidth)
+					break;
+					
+				charPosition = line.getAtomTextBlockEndIndex(atomIndex);
+			}
+			
+			line.flushAtomData();
+			return charPosition;
+		}
+		
+		
+		private function noOpCallback(line:TextLine):void
+		{	
+		}
+		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/factory/TextFlowTextLineFactory.as b/textLayout_core/src/flashx/textLayout/factory/TextFlowTextLineFactory.as
new file mode 100755
index 0000000..42359d1
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/factory/TextFlowTextLineFactory.as
@@ -0,0 +1,261 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.factory
+{
+	import flash.display.Shape;
+	import flash.display.Sprite;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.SimpleCompose;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.OverflowPolicy;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.LineBreak;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+/**
+ * The TextFlowTextLineFactory class provides a simple way to create TextLines for displaying text from a text flow.
+ * 
+ * <p>The text lines are static and created fit in a single bounding rectangle, but can have multiple paragraphs and formats as well as
+ * inline graphics. To create TextLine objects directly from a string, use StringTextLineFactory.</p> 
+ *
+ * <p><b>Note:</b> When using inline graphics, the <code>source</code> property of the InlineGraphicElement object 
+ * must either be an instance of a DisplayObject or a Class object representing an embedded asset. 
+ * URLRequest objects cannot be used. The width and height of the inline graphic at the time the line 
+ * is created is used to compose the flow. </p>
+ * 
+ * @includeExample examples\TextFlowTextLineFactory_example.as 
+ * 
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see flashx.textLayout.elements.TextFlow TextFlow
+ * @see flashx.textLayout.factory.StringTextLineFactory StringTextLineFactory
+*/
+	public final class TextFlowTextLineFactory extends TextLineFactoryBase
+	{
+		/** 
+		 * Creates a TextFlowTextLineFactory object. 
+		 * 
+ 		 * @playerversion Flash 10
+ 		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+ 		 */
+		public function TextFlowTextLineFactory():void
+		{
+			super();
+		}
+
+		/**
+		 * Creates TextLine objects from the specified text flow.
+		 * 
+		 * <p>The text lines are composed to fit the bounds assigned to the <code>compositionBounds</code> property.
+		 * As each line is created, the factory calls the function specified in the 
+		 * <code>callback</code> parameter. This function is passed the TextLine object and
+		 * is responsible for displaying the line. If a line has a background color, the factory also calls the
+		 * callback function with a Shape object containing a rectangle of the background color.</p>
+		 * 
+		 * @param callback function to call with each generated TextLine object.  
+		 * The callback will be called with a Shape object representing any background color (if present), 
+		 * and with TextLine objects for the text.
+		 * @param textFlow The TextFlow from which the lines are created.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */	
+		public function createTextLines(callback:Function,textFlow:TextFlow):void
+		{
+			var measureWidth:Boolean  = isNaN(compositionBounds.width);
+			
+			var bp:String = textFlow.computedFormat.blockProgression;
+						
+			var helper:IFlowComposer = createFlowComposer();
+			helper.swfContext = swfContext;
+
+			helper.addController(containerController);
+			textFlow.flowComposer = helper; 
+			textFlow.backgroundManager = null;
+			
+			_isTruncated = false;
+			
+			// compose
+			containerController.setCompositionSize(compositionBounds.width, compositionBounds.height);
+			containerController.verticalScrollPolicy = truncationOptions ? ScrollPolicy.OFF : verticalScrollPolicy;
+			containerController.horizontalScrollPolicy = truncationOptions ? ScrollPolicy.OFF : horizontalScrollPolicy;
+			textFlow.normalize();
+			textFlow.applyUpdateElements(true);
+
+			helper.compose();
+		
+			// Need truncation if all the following are true
+			// - truncation options exist
+			// - content doesn't fit		
+			if (truncationOptions && !doesComposedTextFit(truncationOptions.lineCountLimit, textFlow.textLength, bp))
+			{
+				_isTruncated = true;
+				var somethingFit:Boolean = false; // were we able to fit something?
+
+				computeLastAllowedLineIndex (truncationOptions.lineCountLimit);	
+				if (_truncationLineIndex >= 0)
+				{					
+					// Create a span for the truncation indicator
+					var truncationIndicatorSpan:SpanElement = new SpanElement();
+					truncationIndicatorSpan.text = truncationOptions.truncationIndicator; 
+					truncationIndicatorSpan.id = "truncationIndicator"; // prevents merging with other spans 
+					if (truncationOptions.truncationIndicatorFormat)
+						truncationIndicatorSpan.format = truncationOptions.truncationIndicatorFormat;
+					
+					var hostFormat:ITextLayoutFormat = textFlow.hostFormat;
+					
+					// Initial truncation position: end of the last allowed line
+					var line:TextLine = _factoryComposer._lines[_truncationLineIndex] as TextLine; 
+					var truncateAtCharPosition:int =  line.userData + line.rawTextLength;
+					
+					// Save off the original lines: used in getNextTruncationPosition
+					// Note that for the original lines to be valid when used, the containing text block should not be modified
+					// Cloning the text flow before modifying it ensures that
+					if (!_pass0Lines)
+						_pass0Lines = new Array();
+					_pass0Lines = _factoryComposer.swapLines(_pass0Lines); 
+
+					// The following loop executes repeatedly composing text until it fits
+					// In each iteration, an atoms's worth of characters of original content is dropped 
+					do
+					{
+						// Clone the part of the flow before the truncation position  
+						textFlow = textFlow.deepCopy(0, truncateAtCharPosition) as TextFlow;
+						// TODO-2/18/2009-deepCopy does not copy hostTextLayoutFormat
+						if (hostFormat)
+							textFlow.hostFormat = hostFormat;
+						
+						// Find a parent for the truncation span
+						var parent:FlowGroupElement;
+						var lastLeaf:FlowLeafElement = textFlow.getLastLeaf();
+						if (lastLeaf)
+						{
+							parent = lastLeaf.parent;
+							// Set format to match the leaf if none specified 
+							if (!truncationOptions.truncationIndicatorFormat)
+								truncationIndicatorSpan.format = lastLeaf.format;
+						}
+						else
+						{
+							parent = new ParagraphElement();
+							textFlow.addChild(parent);
+						}
+					
+						// Append the truncation span (after severing it from the previous flow)
+						if (truncationIndicatorSpan.parent)
+							truncationIndicatorSpan.parent.removeChild(truncationIndicatorSpan);
+						parent.addChild(truncationIndicatorSpan);
+						
+						textFlow.flowComposer = helper;
+						textFlow.normalize();
+						
+						helper.compose();
+			
+						if (doesComposedTextFit(truncationOptions.lineCountLimit, textFlow.textLength, bp))
+						{
+							somethingFit = true;
+							break; 
+						}		
+						
+						if (truncateAtCharPosition == 0)
+							break; // no original content left to make room for truncation indicator
+						
+						// Try again by truncating at the beginning of the preceding atom
+						truncateAtCharPosition = getNextTruncationPosition(truncateAtCharPosition, true);
+
+					} while (true);
+				}
+				
+				if (_truncatedTextFlowCallback != null)
+					_truncatedTextFlowCallback (somethingFit ? textFlow : null);
+					
+				if (!somethingFit)
+					_factoryComposer._lines.splice(0); // return no lines
+			}
+			
+			var xadjust:Number = compositionBounds.x;
+			// toptobottom sets zero to the right edge - adjust the locations
+			var controllerBounds:Rectangle = containerController.getContentBounds();
+			if (bp == BlockProgression.RL)
+				xadjust += (measureWidth ? controllerBounds.width : compositionBounds.width);	
+			
+			// apply x and y adjustment to the bounds
+			controllerBounds.left += xadjust;
+			controllerBounds.right += xadjust;
+			controllerBounds.top += compositionBounds.y;
+			controllerBounds.bottom += compositionBounds.y;
+				
+			if (textFlow.backgroundManager)
+			{
+				var bgShape:Shape = new Shape();
+				textFlow.backgroundManager.drawAllRects(bgShape,containerController);
+				bgShape.x = xadjust;
+				bgShape.y = compositionBounds.y;
+				callback(bgShape);
+				textFlow.backgroundManager = null;
+			}	
+
+			callbackWithTextLines(callback,xadjust,compositionBounds.y);
+
+			setContentBounds(controllerBounds);
+
+			textFlow.changeFlowComposer(null,false);
+			
+			// clear out lines in the FactoryComposer
+			_factoryComposer._lines.splice(0);
+			if (_pass0Lines)
+				_pass0Lines.splice(0);
+		}
+		
+		/** @private 
+		 * Test hook: Sets a callback function for getting the truncated text flow.
+		 * This function is only called if truncation is performed. It takes a single parameter which will have the following value:
+		 * null, if nothing fits
+		 * A text flow representing the truncated text (containing inital text from the original text flow followed by the truncation indicator), otherwise 
+		 */
+		tlf_internal function set truncatedTextFlowCallback(val:Function):void
+		{ _truncatedTextFlowCallback = val; }
+		
+		private var _truncatedTextFlowCallback:Function;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/factory/TextLineFactoryBase.as b/textLayout_core/src/flashx/textLayout/factory/TextLineFactoryBase.as
new file mode 100755
index 0000000..8ae1bbe
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/factory/TextLineFactoryBase.as
@@ -0,0 +1,454 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.factory
+{
+	import flash.display.Sprite;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.ISWFContext;
+	import flashx.textLayout.compose.SimpleCompose;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.OverflowPolicy;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[Exclude(name="containerController",kind="property")]	
+	[Exclude(name="setContentBounds",kind="method")]
+	[Exclude(name="callbackWithTextLines",kind="method")]
+	[Exclude(name="doesComposedTextFit",kind="method")]
+	[Exclude(name="getNextTruncationPosition",kind="method")]
+
+
+/**
+ * The TextLineFactoryBase class serves as the base class for the Text Layout Framework text line factories.
+ * 
+ * <p><b>Note:</b> Application code does not typically need to create or use a TextLineFactoryBase object directly.
+ * Use one of the derived text factory classes instead.</p>
+ *  
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ *
+ * @see flashx.textLayout.elements.TextFlow
+*/
+	public class TextLineFactoryBase
+	{
+		/** Requested logical bounds to wrap to */
+		private var _compositionBounds:Rectangle;
+
+		/** Bounds of composition results - where the text landed */
+		private var _contentBounds:Rectangle;
+		
+		/** @private */
+		protected var _isTruncated:Boolean = false;
+		
+		private var _horizontalScrollPolicy:String;
+		private var _verticalScrollPolicy:String;
+		private var _truncationOptions:TruncationOptions;
+		private var _containerController:ContainerController;
+		static private var _tc:Sprite = new Sprite();
+		
+		private var _swfContext:ISWFContext;
+		
+		/** @private */
+		static tlf_internal var _factoryComposer:SimpleCompose= new SimpleCompose();
+
+		/** @private */		
+		static protected var _truncationLineIndex:int; 	// used during truncation
+		/** @private */		
+		static protected var _pass0Lines:Array; 		// used during truncation
+		
+		/** 
+		 * Base-class constructor for text line factories.
+		 *  
+ 		 * <p><b>Note:</b> Application code does not typically need to create or use a TextLineFactoryBase object directly.
+		 * Use one of the derived text factory classes instead.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TextLineFactoryBase():void
+		{
+			_containerController = new ContainerController(_tc);
+			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);
+		}
+		
+		/**
+		 * The rectangle within which text lines are created.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get compositionBounds():Rectangle
+		{
+			return _compositionBounds;
+		}
+		
+		public function set compositionBounds(value:Rectangle):void
+		{
+			_compositionBounds = value;
+		}
+		
+		/**
+		 * The smallest rectangle in which the layed-out content fits.
+		 * 
+		 * <p><b>Note:</b> Truncated lines are not included in the size calculation.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function getContentBounds():Rectangle
+		{
+			return _contentBounds;
+		}
+		
+		/** @private */
+		protected function setContentBounds(controllerBounds:Rectangle):void
+		{
+			_contentBounds = controllerBounds;
+			_contentBounds.offset(compositionBounds.left, compositionBounds.top);
+		}
+		
+		/** 
+		* The ISWFContext instance used to make FTE calls as needed. 
+		*
+		* <p>By default, the ISWFContext implementation is this FlowComposerBase object.
+		* Applications can provide a custom implementation to use fonts
+		* embedded in a different SWF file or to cache and reuse text lines.</p>
+		* 
+		* @see flashx.textLayout.compose.ISWFContext
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+ 	
+		public function get swfContext():ISWFContext
+		{
+			return _swfContext;
+		}
+		public function set swfContext(value:ISWFContext):void
+		{
+			_swfContext = value;
+		}
+		
+		/** 
+		 * Specifies the options for truncating the text if it doesn't fit in the composition bounds.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get truncationOptions():TruncationOptions
+		{
+			return _truncationOptions;
+		}
+		public function set truncationOptions(value:TruncationOptions):void
+		{
+			_truncationOptions = value;
+		}
+		
+		/** 
+		 * Indicates whether text was truncated when lines were last created.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get isTruncated():Boolean
+		{
+			return _isTruncated;
+		}
+
+		/** 
+		 * Specifies how lines are created when the composition bounds are not large enough.
+		 *  
+		 * <p>If set to <code>ScrollPolicy.ON</code> or <code>ScrollPolicy.AUTO</code>, all lines
+		 * are created. It is the your responsibility to scroll lines in the viewable area (and to
+		 * mask lines outside this area, if necessary). If set to <code>ScrollPolicy.OFF</code>, then 
+		 * only lines that fit within the composition bounds are created.</p>
+		 * 
+		 * <p>If the <code>truncationOptions</code> property is set, the scroll policy is ignored 
+		 * (and treated as <code>ScrollPolicy.OFF</code>).</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.StandardFlowComposer
+		 * @see flashx.textLayout.container.ScrollPolicy
+		 * @see #truncationOptions
+	 	 */
+	 	 
+	 	public function get horizontalScrollPolicy():String
+		{
+			return _horizontalScrollPolicy;
+		}
+		public function set horizontalScrollPolicy(scrollPolicy:String):void
+		{
+			_horizontalScrollPolicy =  scrollPolicy;
+		}
+		
+		/** 
+		 * Specifies how lines are created when the composition bounds are not large enough.
+		 *  
+		 * <p>If set to <code>ScrollPolicy.ON</code> or <code>ScrollPolicy.AUTO</code>, all lines
+		 * are created. It is the your responsibility to scroll lines in the viewable area (and to
+		 * mask lines outside this area, if necessary). If set to <code>ScrollPolicy.OFF</code>, then 
+		 * only lines that fit within the composition bounds are created.</p>
+		 * 
+		 * <p>If the <code>truncationOptions</code> property is set, the scroll policy is ignored 
+		 * (and treated as <code>ScrollPolicy.OFF</code>).</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.compose.StandardFlowComposer
+		 * @see flashx.textLayout.container.ScrollPolicy
+		 * @see #truncationOptions
+	 	 */
+	 	 
+		public function get verticalScrollPolicy():String
+		{
+			return _verticalScrollPolicy;
+		}
+		public function set verticalScrollPolicy(scrollPolicy:String):void
+		{
+			_verticalScrollPolicy =  scrollPolicy;
+		}		
+		
+		/** @private */
+		tlf_internal static function getDefaultFlowComposerClass():Class
+		{
+			return FactoryDisplayComposer;
+		}
+		
+		/** @private */
+		protected function get containerController():ContainerController
+		{
+			return _containerController;
+		}
+		
+		/** 
+		 * Sends the created TextLine objects to the client using the supplied callback function.
+		 * 
+		 * <p>This method sets the <code>x</code> and <code>y</code> properties of the line.</p>
+		 * 
+		 * @param callback the callback function supplied by the factory user
+		 * @param delx the horizontal offset
+		 * @param dely the vertical offset
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		protected function callbackWithTextLines(callback:Function,delx:Number,dely:Number):void
+		{
+			for each (var textLine:TextLine in _factoryComposer._lines)
+			{
+				var textBlock:TextBlock = textLine.textBlock;
+				if (textBlock)
+				{
+					CONFIG::debug { Debugging.traceFTECall(null,textBlock,"releaseLines",textBlock.firstLine, textBlock.lastLine); }	
+					textBlock.releaseLines(textBlock.firstLine,textBlock.lastLine);
+				}
+				textLine.userData = null;
+				textLine.x += delx;
+				textLine.y += dely;
+				textLine.validity = TextLineValidity.STATIC;
+				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",TextLineValidity.STATIC); }
+				callback(textLine);
+			}
+		}
+		
+		/**
+		 * Indicates whether the composed text fits in the line count limit and includes all text
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */	
+		protected function doesComposedTextFit (lineCountLimit:int, textLength:uint, blockProgression:String):Boolean
+		{
+			if (lineCountLimit != TruncationOptions.NO_LINE_COUNT_LIMIT && _factoryComposer._lines.length > lineCountLimit)
+				return false; // Line count limit exceded
+			
+			var lines:Array = _factoryComposer._lines;
+		
+			if (!lines.length)
+				return textLength ? false /* something to compose, but no line could fit */ : true /* nothing to compose */; 
+				
+			// This code is only called when scrolling if OFF, so only lines that fit in bounds are generated
+			// Just check if the last line reaches the end of flow
+			var lastLine:TextLine = lines[lines.length - 1] as TextLine;
+			return lastLine.userData + lastLine.rawTextLength == textLength;
+		}
+		
+		/** 
+		 * Gets the next truncation position by shedding an atom's worth of characters.
+		 * 
+		 * @param truncateAtCharPosition the current truncation candidate position.
+		 * @param multiPara <code>true</code> if text has more than one paragraph.
+		 * 
+		 * @returns the next candidate truncation position.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		protected function getNextTruncationPosition(truncateAtCharPosition:int, multiPara:Boolean=false):int
+		{
+			// 1. Get the position of the last character of the preceding atom
+			truncateAtCharPosition--; // truncateAtCharPosition-1, because truncateAtCharPosition is an atom boundary
+			
+			// Note: The current set of lines may not contain the next truncation position because the truncation indicator
+			// could combine with original content to form a word that does not afford a suitable break opportunity. 
+			// The combined word would then move to the next line, which may not have been composed if the bounds were exceeded.
+			// Therefore, this function needs to use the original lines (from before truncation is attempted). 
+			CONFIG::debug 
+			{ 
+				assert(_pass0Lines != null, "getNextTruncationPosition called before saving off lines from the first pass at composition"); 
+				assert(_truncationLineIndex < _pass0Lines.length, "index out of range in getNextTruncationPosition");
+			}
+			
+			// 2. Find the new target line (i.e., the line that has the new truncation position) 
+			// If the last truncation position was at the beginning of the target line, the new position may have moved to a previous line
+			// In any case, the new truncation position lies in the vicinity of the previous target line, so a linear search suffices
+			var line:TextLine = _pass0Lines[_truncationLineIndex] as TextLine;
+			do
+			{
+				if (truncateAtCharPosition >= line.userData && truncateAtCharPosition < line.userData + line.rawTextLength)
+					break;
+				if (truncateAtCharPosition < line.userData)
+					line = _pass0Lines[--_truncationLineIndex] as TextLine;
+				else
+				{
+					CONFIG::debug {	assert(false, "truncation position should decrease monotonically");	}
+				}	
+			}
+			while (true);
+
+			var paraStart:int = multiPara ?  line.userData - line.textBlockBeginIndex : 0;
+			
+			// 3. Get the line atom index at this position			
+			var atomIndex:int = line.getAtomIndexAtCharIndex(truncateAtCharPosition - paraStart);
+			
+			// 4. Get the char index for this atom index
+			var nextTruncationPosition:int = line.getAtomTextBlockBeginIndex(atomIndex) + paraStart;
+			
+			line.flushAtomData();
+			
+			return nextTruncationPosition;
+		} 
+		/** @private */
+		tlf_internal function createFlowComposer():IFlowComposer
+		{
+			return new FactoryDisplayComposer();
+		}			
+		
+		/** @private
+		 * Calculates the last line that fits in the line count limit
+		 * The result is stored in  _truncationLineIndex
+		 * 
+		 * Note: This code is only called when scrolling is OFF, so only lines that fit in bounds are generated
+		 */
+		tlf_internal function computeLastAllowedLineIndex (lineCountLimit:int):void
+		{			
+			_truncationLineIndex = _factoryComposer._lines.length - 1;
+
+			// if line count limit is smaller, use that
+			if (lineCountLimit != TruncationOptions.NO_LINE_COUNT_LIMIT && lineCountLimit <= _truncationLineIndex)
+				_truncationLineIndex = lineCountLimit - 1;
+		}
+	}
+
+} // end package
+
+import flash.geom.Rectangle;
+
+import flashx.textLayout.compose.StandardFlowComposer;
+import flashx.textLayout.compose.SimpleCompose;
+import flashx.textLayout.debug.assert;
+import flashx.textLayout.elements.BackgroundManager;
+import flashx.textLayout.elements.FlowLeafElement;
+import flashx.textLayout.compose.TextFlowLine;
+import flashx.textLayout.factory.TextLineFactoryBase;
+import flashx.textLayout.tlf_internal;
+import flash.text.engine.TextLine;
+import flashx.textLayout.container.ContainerController;
+import flashx.textLayout.compose.TextFlowLine;
+use namespace tlf_internal;
+
+class FactoryDisplayComposer extends StandardFlowComposer
+{
+	tlf_internal override function callTheComposer(absoluteEndPosition:int, controllerEndIndex:int):ContainerController
+	{
+		// always do a full compose
+		clearCompositionResults();
+		
+		var state:SimpleCompose = TextLineFactoryBase._factoryComposer;
+		state.composeTextFlow(textFlow, -1, -1);
+		state.releaseAnyReferences()
+		return getControllerAt(0);
+	}
+		
+	/** Returns true if composition is necessary, false otherwise */
+	protected override function preCompose():Boolean
+	{
+		return true;
+	}
+	
+	/** @private */
+	public override function createBackgroundManager():BackgroundManager
+	{ return new FactoryBackgroundManager(); }
+}
+
+class FactoryBackgroundManager extends BackgroundManager
+{
+
+	public override function finalizeLine(line:TextFlowLine):void
+	{
+		var textLine:TextLine = line.getTextLine();
+		
+		var array:Array = lineDict[textLine];
+		if (array)
+		{
+			// attach the columnRect and the TextLine to the first object in the Array
+			var obj:Object = array[0];
+			
+			if (obj)	// check not needed?
+				obj.columnRect = line.controller.columnState.getColumnAt(line.columnIndex);
+		}
+	}
+}
+
diff --git a/textLayout_core/src/flashx/textLayout/factory/TruncationOptions.as b/textLayout_core/src/flashx/textLayout/factory/TruncationOptions.as
new file mode 100755
index 0000000..aa333f4
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/factory/TruncationOptions.as
@@ -0,0 +1,154 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.factory
+{
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	
+	/** 
+	 * The TruncationOptions class specifies options for limiting the number of lines of text 
+	 * created by a text line factory and for indicating when lines have been left out.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class TruncationOptions
+	{
+		/** 
+		 * Creates a TruncationOptions object.
+		 * 
+		 * @param truncationIndicator the string used to indicate that text has been truncated. 
+		 * It appears at the end of the composed text. The default value is the horizontal ellipsis (U+2026).
+		 * @param lineCountLimit specifies a truncation criterion in the form of the maximum 
+		 * number of lines allowed. The default value of <code>NO_LINE_COUNT_LIMIT</code> 
+		 * indicates that there is no line count limit.
+		 * @param truncationIndicatorFormat specifies the format for the truncation indicator. 
+		 * A null format (the default value) specifies that the truncation indicator assume 
+		 * the format of content just before the truncation point. The <code>TextLineFactory</code> 
+		 * methods that take a simple string as input also ignore this parameter and implement 
+		 * the default behavior.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TruncationOptions (truncationIndicator:String=HORIZONTAL_ELLIPSIS, lineCountLimit:int=NO_LINE_COUNT_LIMIT, truncationIndicatorFormat:ITextLayoutFormat=null)
+		{
+			this.truncationIndicator =  truncationIndicator;
+			this.truncationIndicatorFormat = truncationIndicatorFormat;
+			this.lineCountLimit = lineCountLimit;
+		}
+		
+		/** 
+		 * A string used to indicate that content could not be fully displayed
+		 * because of limits on the number of lines.
+		 * 
+		 * @return the truncation indicator
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get truncationIndicator():String
+		{
+			return _truncationIndicator ? _truncationIndicator : HORIZONTAL_ELLIPSIS;
+		}
+		/** 
+		 * Sets the truncation indicator
+		 * @param val the string used to indicate that text has been truncated
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function set truncationIndicator(val:String):void
+		{
+			_truncationIndicator = val;
+		}
+		
+		/** 
+		 * The style applied to the truncation indicator string.
+		 * @return the format truncation indicator
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get truncationIndicatorFormat():ITextLayoutFormat
+		{
+			return _truncationIndicatorFormat;
+		}
+		/** 
+		 * Sets the styles applied to the truncation indicator character
+		 * 
+		 * @param val specifies the format for the truncation indicator. A null format specifies that the truncation indicator assume the format of content
+		 * just before the truncation point. The <code>TextLineFactory</code> methods that take a simple string as input also ignore this parameter and implement the default behavior
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function set truncationIndicatorFormat(val:ITextLayoutFormat):void
+		{
+			_truncationIndicatorFormat = val;
+		}
+		
+		/** 
+		 * The maximum number of lines to create.
+		 * @return the line count limit
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineCountLimit():int
+		{
+			return _lineCountLimit < NO_LINE_COUNT_LIMIT ? 0 : _lineCountLimit;
+		}
+		/** 
+		 * Sets the maximum number of lines to create
+		 * @param val specifies the maximum number of lines allowed. 
+		 * A value of <code>NO_LINE_COUNT_LIMIT</code> indicates that there is no line count limit.
+		 */
+		public function set lineCountLimit(val:int):void
+		{
+			_lineCountLimit = val;
+		} 
+		
+		private var _truncationIndicator:String;
+		private var _truncationIndicatorFormat:ITextLayoutFormat;
+		private var _lineCountLimit:int;
+		
+		/**
+		 * Defines the <code>lineCountLimit</code> property value, <code>-1</code>, that represents no limit.
+		 *
+		 * @see #lineCountLimit
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static const NO_LINE_COUNT_LIMIT:int = -1;
+
+		/**
+		 * Defines the <code>truncationIndicator</code> property value, <code>\u2026</code>, that represents a horizontal ellipsis.
+		 *
+		 * @see #truncationIndicator
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static const HORIZONTAL_ELLIPSIS:String = "\u2026";
+	}	
+}
+
+
diff --git a/textLayout_core/src/flashx/textLayout/formats/BackgroundColor.as b/textLayout_core/src/flashx/textLayout/formats/BackgroundColor.as
new file mode 100755
index 0000000..ca48aa2
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/BackgroundColor.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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines a constant for specifying that the value of the <code>backgroundColor</code> property
+	 *  of the <code>TextLayoutFormat</code> class is "transparent".
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * @see flashx.textLayout.formats.TextLayoutFormat#backgroundColor TextLayoutFormat.backgroundColor
+	 */
+	public final class BackgroundColor
+	{
+		/** Transparent - no background color is applied.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const TRANSPARENT:String = "transparent";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/BaselineOffset.as b/textLayout_core/src/flashx/textLayout/formats/BaselineOffset.as
new file mode 100755
index 0000000..1a02b65
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/BaselineOffset.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for the <code>firstBaselineOffset</code> property
+	 *  of the <code>TextLayoutFormat</code> and <code>ContainerFormattedElement</code> classes. 
+	 *  Determines the offset from the top inset of the container
+	 *  to the baseline of the first line. Baseline offset may be specified as 
+	 *  the ascent of the line, the height of the line, or an auto generated amount.
+	 *  <p>
+	 *  <img src="../../../images/textLayout_FBO1.jpg" alt="firstBaselineOffset_1" border="0"/>
+	 *  <img src="../../../images/textLayout_FBO2.jpg" alt="firstBaselineOffset_2" border="0"/>
+	 *  <img src="../../../images/textLayout_FBO3.jpg" alt="firstBaselineOffset_3" border="0"/>
+	 *  <img src="../../../images/textLayout_FBO4.jpg" alt="firstBaselineOffset_4" border="0"/>
+	 *  </p>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  @see TextLayoutFormat#firstBaselineOffset
+	 */
+	public final class BaselineOffset
+	{
+		/** Aligns the ascent of the line with the container top inset.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const AUTO:String = "auto";
+		
+		/** Specifies an offset equal to the ascent of the line, that is, the ascent of the tallest font in the line, accounting for inline graphics as having the bottom of the graphic on the baseline.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public static const ASCENT:String = "ascent";
+		
+		/** Specifies an offset equal to the height of the line.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const LINE_HEIGHT:String = "lineHeight";		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/BaselineShift.as b/textLayout_core/src/flashx/textLayout/formats/BaselineShift.as
new file mode 100755
index 0000000..e446416
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/BaselineShift.as
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines constants for specifying subscript or superscript in the <code>baselineShift</code> property
+	 *  of the <code>TextLayoutFormat</code> class. You can specify baseline shift as an absolute pixel offset, 
+	 *  a percentage of the current point size, or the constants SUPERSCRIPT or 
+	 *  SUBSCRIPT. Positive values shift the line up for horizontal text (right for vertical) and negative values 
+	 *  shift it down for horizontal (left for vertical). 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 *  @see flashx.textLayout.formats.TextLayoutFormat#baselineShift TextLayoutFormat.baselineShift
+	 */
+	public final class BaselineShift
+	{
+		/** Shifts baseline to the current superscript position.
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const SUPERSCRIPT:String = "superscript";
+		
+		/** Shifts baseline to the current subscript position.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public static const SUBSCRIPT:String = "subscript";		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/BlockProgression.as b/textLayout_core/src/flashx/textLayout/formats/BlockProgression.as
new file mode 100755
index 0000000..23aa355
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/BlockProgression.as
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for the <code>blockProgression</code> property
+	 *  of the <code>TextLayouFormat</code> class. BlockProgression specifies the direction in 
+	 *  which lines are placed in the container.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * 
+	 *  @see flashx.textLayout.formats.TextLayoutFormat#blockProgression TextLayoutFormat.blockProgression
+	 */
+	 
+	public final class BlockProgression
+	{
+		/** 
+		 *  Specifies right to left block progression. Lines are laid out vertically starting at the right 
+		 *  edge of the container and progressing leftward. Used for vertical text, for example, vertical 
+		 *  Chinese or Japanese text. 
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	  	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const RL:String = "rl";
+		
+		/** 
+		 *  Specifies top to bottom block progression. Lines are laid out horizontally starting at the top of 
+		 *  the container and progressing down to the bottom. Used for horizontal text. 
+		 * 
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	  	 * @langversion 3.0 
+	  	 */
+	  	 
+		public static const TB:String = "tb";				
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/Category.as b/textLayout_core/src/flashx/textLayout/formats/Category.as
new file mode 100755
index 0000000..f31efad
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/Category.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 flashx.textLayout.formats
+{
+	/**
+	 *  Property categories
+	 * @private
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  @see flashx.textLayout.elements.ParagraphFormattedElement
+	 */
+	public final class Category
+	{
+		public static const PARAGRAPH:String = "Paragraph";
+		public static const CONTAINER:String = "Container";
+		public static const CHARACTER:String = "Character";
+		public static const TABSTOP:String = "TabStop";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/Direction.as b/textLayout_core/src/flashx/textLayout/formats/Direction.as
new file mode 100755
index 0000000..fc1469b
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/Direction.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>direction</code> property
+	 *  of the <code>TextLayoutFormat</code> class. Left-to-right reading order 
+	 *  is used in Latin-style scripts. Right-to-left reading order is used with scripts such as Arabic or Hebrew. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * @see TextLayoutFormat#direction 
+	 */
+	public final class Direction
+	{
+		/** Specifies left-to-right direction for text. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const LTR:String = "ltr";
+		
+		/** Specifies right-to-left direction for text. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const RTL:String = "rtl";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/Float.as b/textLayout_core/src/flashx/textLayout/formats/Float.as
new file mode 100755
index 0000000..dd0eea8
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/Float.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 flashx.textLayout.formats
+{
+	/**
+	 *  Some of the values for the <code>float</code> property
+	 *  of the InlineGraphicElement class. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  @see text.InlineGrapic
+	 * @private - still in prototype phase
+	 */
+	public final class Float
+	{
+		/** None - graphic will appear inline in the text (doesn't float) */
+		public static const NONE:String = "none";		
+		/** Left - graphic will float on the left side of the text */
+		public static const LEFT:String = "left";
+		/** Right - graphic will float on the right side of the text */
+		public static const RIGHT:String = "right";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/FlowElementDisplayType.as b/textLayout_core/src/flashx/textLayout/formats/FlowElementDisplayType.as
new file mode 100755
index 0000000..16ceded
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/FlowElementDisplayType.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 flashx.textLayout.formats
+{
+[ExcludeClass]
+	/**
+	 * An enumeration to describe how a FlowElement should be treated when composed. 
+	 * @see text.elements.FlowElement#display
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * These APIs are still in prototype phase
+	 * @private
+	 */
+	public final class FlowElementDisplayType 
+	{
+			/** Element appears inline in the text; it is placed in its parent's geometry context */
+		public static const INLINE:String = "inline";
+			/** Element floats with the text, but supplies its own geometry context (e.g., a sidebar or table) */
+		public static const FLOAT:String = "float";	
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/FormatValue.as b/textLayout_core/src/flashx/textLayout/formats/FormatValue.as
new file mode 100755
index 0000000..d544a75
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/FormatValue.as
@@ -0,0 +1,55 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for specifying that a formatting property is to inherit its parent's value or have it's value
+	 *  generated automatically. The <code>INHERIT</code> constant specifies that a property inherits its parent's value 
+	 *  while the <code>AUTO</code> constant specifies that an internal algorithm automatically determine the property's 
+	 *  value. As one example, you can set <code>TextLayoutFormat.columnWidth</code> using these values. Typically, a 
+	 *  property's description indicates whether it accepts these constants.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *
+	 * @see flashx.textLayout.formats.TextLayoutFormat TextLayoutFormat
+	 */
+	 
+	public final class FormatValue
+	{
+		/** Specifies that a property's value is automatically generated. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const AUTO:String = "auto";
+		
+		/** Specifies that a property is to inherit its parent's value.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const INHERIT:String = "inherit";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/IMEStatus.as b/textLayout_core/src/flashx/textLayout/formats/IMEStatus.as
new file mode 100755
index 0000000..a0b0e45
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/IMEStatus.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 flashx.textLayout.formats
+{
+	[ExcludeClass]
+	/**
+	 *  Used internally for specifying the status of clauses in IME text during an IME text entry session.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public final class IMEStatus
+	{
+		public function IMEStatus()
+		{
+		}
+		
+		/** The name of the IMEClause property. Value is an integer.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const IME_CLAUSE:String = "imeClause";
+		
+		/** The name of the IMEStatus property
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const IME_STATUS:String = "imeStatus";
+		
+		// Following are all the possible values of imeStatus property:
+		
+		/** Selected raw - text has not been converted and is the current clause in the IME session
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const SELECTED_RAW:String = "selectedRaw";
+
+		/** Selected coverted - text has been converted and is the current clause in the IME session
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const SELECTED_CONVERTED:String = "selectedConverted";
+
+		/** Not selected raw - text has not been converted and is not part of the current clause 
+		 *  in the IME session
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const NOT_SELECTED_RAW:String = "notSelectedRaw";
+		
+		/** Not selected converted - text has been converted and is not part of the current clause 
+		 * 	in the IME session
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const NOT_SELECTED_CONVERTED:String = "notSelectedConverted";
+
+		/** Dead key input state - in the process of entering a multi-key character, such as an accented char
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public static const DEAD_KEY_INPUT_STATE:String = "deadKeyInputState";
+
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/ITabStopFormat.as b/textLayout_core/src/flashx/textLayout/formats/ITabStopFormat.as
new file mode 100755
index 0000000..d51b50b
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/ITabStopFormat.as
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 * This interface provides read access to tab stop-related properties.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface ITabStopFormat
+	{
+		/**
+		 * The position of the tab stop, in pixels, relative to the start of the line.
+		 * <p>Legal values are numbers from 0 to 10000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * @see FormatValue#INHERIT
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get position():*;
+
+		/**
+		 * The tab alignment for this tab stop. 
+		 * <p>Legal values are flash.text.engine.TabAlignment.START, flash.text.engine.TabAlignment.CENTER, flash.text.engine.TabAlignment.END, flash.text.engine.TabAlignment.DECIMAL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of START.</p>
+		 * @see FormatValue#INHERIT
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TabAlignment
+		 */
+		function get alignment():*;
+
+		/**
+		 * The alignment token to be used if the alignment is DECIMAL.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get decimalAlignmentToken():*;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/ITextLayoutFormat.as b/textLayout_core/src/flashx/textLayout/formats/ITextLayoutFormat.as
new file mode 100755
index 0000000..5acb152
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/ITextLayoutFormat.as
@@ -0,0 +1,816 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 * This interface provides read access to FlowElements-related properties.
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public interface ITextLayoutFormat
+	{
+		/**
+		 * Color of the text. A hexadecimal number that specifies three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get color():*;
+
+		/**
+		 * Background color of the text (adopts default value if undefined during cascade). Can be either the constant value  <code>BackgroundColor.TRANSPARENT</code>, or a hexadecimal value that specifies the three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green.
+		 * <p>Legal values as a string are flashx.textLayout.formats.BackgroundColor.TRANSPARENT, flashx.textLayout.formats.FormatValue.INHERIT and uints from 0x0 to 0xffffffff.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TRANSPARENT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BackgroundColor
+		 */
+		function get backgroundColor():*;
+
+		/**
+		 * If <code>true</code>, applies strikethrough, a line drawn through the middle of the text.
+		 * <p>Legal values are true, false and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of false.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get lineThrough():*;
+
+		/**
+		 * Alpha (transparency) value for the text. A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with <code>textAlpha</code> set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get textAlpha():*;
+
+		/**
+		 * Alpha (transparency) value for the background (adopts default value if undefined during cascade). A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with alpha set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get backgroundAlpha():*;
+
+		/**
+		 * The size of the text in pixels.
+		 * <p>Legal values are numbers from 1 to 720 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 12.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get fontSize():*;
+
+		/**
+		 * Amount to shift the baseline from the <code>dominantBaseline</code> value. Units are in pixels, or a percentage of <code>fontSize</code> (in which case, enter a string value, like 140%).  Positive values shift the line up for horizontal text (right for vertical) and negative values shift it down for horizontal (left for vertical). 
+		 * <p>Legal values are flashx.textLayout.formats.BaselineShift.SUPERSCRIPT, flashx.textLayout.formats.BaselineShift.SUBSCRIPT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineShift
+		 */
+		function get baselineShift():*;
+
+		/**
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the left of each character. If kerning is enabled, the <code>trackingLeft</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingLeft</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get trackingLeft():*;
+
+		/**
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the right of each character.  If kerning is enabled, the <code>trackingRight</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingRight</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get trackingRight():*;
+
+		/**
+		 * Leading controls for the text. The distance from the baseline of the previous or the next line (based on <code>LeadingModel</code>) to the baseline of the current line is equal to the maximum amount of the leading applied to any character in the line. This is either a number or a percent.  If specifying a percent, enter a string value, like 140%.<p><img src='../../../images/textLayout_lineHeight1.jpg' alt='lineHeight1' /><img src='../../../images/textLayout_lineHeight2.jpg' alt='lineHeight2' /></p>
+		 * <p>Legal values as a number are from -720 to 720.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 120%.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get lineHeight():*;
+
+		/**
+		 * Controls where lines are allowed to break when breaking wrapping text into multiple lines. Set to <code>BreakOpportunity.AUTO</code> to break text normally. Set to <code>BreakOpportunity.NONE</code> to <em>not</em> break the text unless the text would overrun the measure and there are no other places to break the line. Set to <code>BreakOpportunity.ANY</code> to allow the line to break anywhere, rather than just between words. Set to <code>BreakOpportunity.ALL</code> to have each typographic cluster put on a separate line (useful for text on a path).
+		 * <p>Legal values are flash.text.engine.BreakOpportunity.ALL, flash.text.engine.BreakOpportunity.ANY, flash.text.engine.BreakOpportunity.AUTO, flash.text.engine.BreakOpportunity.NONE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.BreakOpportunity
+		 */
+		function get breakOpportunity():*;
+
+		/**
+		 * The type of digit case used for this text. Setting the value to <code>DigitCase.OLD_STYLE</code> approximates lowercase letterforms with varying ascenders and descenders. The figures are proportionally spaced. This style is only available in selected typefaces, most commonly in a supplemental or expert font. The <code>DigitCase.LINING</code> setting has all-cap height and is typically monospaced to line up in charts.<p><img src='../../../images/textLayout_digitcase.gif' alt='digitCase' /></p>
+		 * <p>Legal values are flash.text.engine.DigitCase.DEFAULT, flash.text.engine.DigitCase.LINING, flash.text.engine.DigitCase.OLD_STYLE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitCase
+		 */
+		function get digitCase():*;
+
+		/**
+		 * Type of digit width used for this text. This can be <code>DigitWidth.PROPORTIONAL</code>, which looks best for individual numbers, or <code>DigitWidth.TABULAR</code>, which works best for numbers in tables, charts, and vertical rows.<p><img src='../../../images/textLayout_digitwidth.gif' alt='digitWidth' /></p>
+		 * <p>Legal values are flash.text.engine.DigitWidth.DEFAULT, flash.text.engine.DigitWidth.PROPORTIONAL, flash.text.engine.DigitWidth.TABULAR, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitWidth
+		 */
+		function get digitWidth():*;
+
+		/**
+		 * Specifies which element baseline snaps to the <code>alignmentBaseline</code> to determine the vertical position of the element on the line. A value of <code>TextBaseline.AUTO</code> selects the dominant baseline based on the <code>locale</code> property of the parent paragraph.  For Japanese and Chinese, the selected baseline value is <code>TextBaseline.IDEOGRAPHIC_CENTER</code>; for all others it is <code>TextBaseline.ROMAN</code>. These baseline choices are determined by the choice of font and the font size.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO, flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		function get dominantBaseline():*;
+
+		/**
+		 * Kerning adjusts the pixels between certain character pairs to improve readability. Kerning is supported for all fonts with kerning tables.
+		 * <p>Legal values are flash.text.engine.Kerning.ON, flash.text.engine.Kerning.OFF, flash.text.engine.Kerning.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.Kerning
+		 */
+		function get kerning():*;
+
+		/**
+		 * Controls which of the ligatures that are defined in the font may be used in the text. The ligatures that appear for each of these settings is dependent on the font. A ligature occurs where two or more letter-forms are joined as a single glyph. Ligatures usually replace consecutive characters sharing common components, such as the letter pairs 'fi', 'fl', or 'ae'. They are used with both Latin and Non-Latin character sets. The ligatures enabled by the values of the LigatureLevel class - <code>MINIMUM</code>, <code>COMMON</code>, <code>UNCOMMON</code>, and <code>EXOTIC</code> - are additive. Each value enables a new set of ligatures, but also includes those of the previous types.<p><b>Note: </b>When working with Arabic or Syriac fonts, <code>ligatureLevel</code> must be set to MINIMUM or above.</p><p><img src='../../../images/textLayout_ligatures.png' alt='ligatureLevel' /></p>
+		 * <p>Legal values are flash.text.engine.LigatureLevel.MINIMUM, flash.text.engine.LigatureLevel.COMMON, flash.text.engine.LigatureLevel.UNCOMMON, flash.text.engine.LigatureLevel.EXOTIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COMMON.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.LigatureLevel
+		 */
+		function get ligatureLevel():*;
+
+		/**
+		 * Specifies the baseline to which the dominant baseline aligns. For example, if you set <code>dominantBaseline</code> to ASCENT, setting <code>alignmentBaseline</code> to DESCENT aligns the top of the text with the DESCENT baseline, or below the line.  The largest element in the line generally determines the baselines.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of USE_DOMINANT_BASELINE.</p>
+		 * @includeExample examples\TextLayoutFormat_alignmentBaselineExample.as -noswf
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		function get alignmentBaseline():*;
+
+		/**
+		 * The locale of the text. Controls case transformations and shaping. Standard locale identifiers as described in Unicode Technical Standard #35 are used. For example en, en_US and en-US are all English, ja is Japanese. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of en.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get locale():*;
+
+		/**
+		 * The type of typographic case used for this text. Here are some examples:<p><img src='../../../images/textLayout_typographiccase.png' alt='typographicCase' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.TLFTypographicCase.DEFAULT, flashx.textLayout.formats.TLFTypographicCase.CAPS_TO_SMALL_CAPS, flashx.textLayout.formats.TLFTypographicCase.UPPERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TLFTypographicCase
+		 */
+		function get typographicCase():*;
+
+		/**
+		 *  The name of the font to use, or a comma-separated list of font names. The Flash runtime renders the element with the first available font in the list. For example Arial, Helvetica, _sans causes the player to search for Arial, then Helvetica if Arial is not found, then _sans if neither is found.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of Arial.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get fontFamily():*;
+
+		/**
+		 * Decoration on text. Use to apply underlining; default is none.
+		 * <p>Legal values are flashx.textLayout.formats.TextDecoration.NONE, flashx.textLayout.formats.TextDecoration.UNDERLINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NONE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextDecoration
+		 */
+		function get textDecoration():*;
+
+		/**
+		 * Weight of text. May be <code>FontWeight.NORMAL</code> for use in plain text, or <code>FontWeight.BOLD</code>. Applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontWeight.NORMAL, flash.text.engine.FontWeight.BOLD, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontWeight
+		 */
+		function get fontWeight():*;
+
+		/**
+		 * Style of text. May be <code>FontPosture.NORMAL</code>, for use in plain text, or <code>FontPosture.ITALIC</code> for italic. This property applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontPosture.NORMAL, flash.text.engine.FontPosture.ITALIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontPosture
+		 */
+		function get fontStyle():*;
+
+		/**
+		 * Collapses or preserves whitespace when importing text into a TextFlow. <code>WhiteSpaceCollapse.PRESERVE</code> retains all whitespace characters. <code>WhiteSpaceCollapse.COLLAPSE</code> removes newlines, tabs, and leading or trailing spaces within a block of imported text. Line break tags (<br/>) and Unicode line separator characters are retained.
+		 * <p>Legal values are flashx.textLayout.formats.WhiteSpaceCollapse.PRESERVE, flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COLLAPSE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.WhiteSpaceCollapse
+		 */
+		function get whiteSpaceCollapse():*;
+
+		/**
+		 * The rendering mode used for this text.  Applies only to embedded fonts (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>).
+		 * <p>Legal values are flash.text.engine.RenderingMode.NORMAL, flash.text.engine.RenderingMode.CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of CFF.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.RenderingMode
+		 */
+		function get renderingMode():*;
+
+		/**
+		 * The type of CFF hinting used for this text. CFF hinting determines whether the Flash runtime forces strong horizontal stems to fit to a sub pixel grid or not. This property applies only if the <code>renderingMode</code> property is set to <code>RenderingMode.CFF</code>, and the font is embedded (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>). At small screen sizes, hinting produces a clear, legible text for human readers.
+		 * <p>Legal values are flash.text.engine.CFFHinting.NONE, flash.text.engine.CFFHinting.HORIZONTAL_STEM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of HORIZONTAL_STEM.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.CFFHinting
+		 */
+		function get cffHinting():*;
+
+		/**
+		 * Font lookup to use. Specifying <code>FontLookup.DEVICE</code> uses the fonts installed on the system that is running the SWF file. Device fonts result in a smaller movie size, but text is not always rendered the same across different systems and platforms. Specifying <code>FontLookup.EMBEDDED_CFF</code> uses font outlines embedded in the published SWF file. Embedded fonts increase the size of the SWF file (sometimes dramatically), but text is consistently displayed in the chosen font.
+		 * <p>Legal values are flash.text.engine.FontLookup.DEVICE, flash.text.engine.FontLookup.EMBEDDED_CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEVICE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontLookup
+		 */
+		function get fontLookup():*;
+
+		/**
+		 * Determines the number of degrees to rotate this text.
+		 * <p>Legal values are flash.text.engine.TextRotation.ROTATE_0, flash.text.engine.TextRotation.ROTATE_180, flash.text.engine.TextRotation.ROTATE_270, flash.text.engine.TextRotation.ROTATE_90, flash.text.engine.TextRotation.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextRotation
+		 */
+		function get textRotation():*;
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the first line of the paragraph.
+		 * A negative indent will push the line into the margin, and possibly out of the container.
+		 * <p>Legal values are numbers from -1000 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get textIndent():*;
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's start edge. Refers to the left edge in left-to-right text and the right edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paragraphStartIndent():*;
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's end edge. Refers to the right edge in left-to-right text and the left edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paragraphEndIndent():*;
+
+		/**
+		 * A Number that specifies the amount of space, in pixels, to leave before the paragraph. 
+		 * Collapses in tandem with <code>paragraphSpaceAfter</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paragraphSpaceBefore():*;
+
+		/**
+		 * A Number that specifies the amount of space, in pixels, to leave after the paragraph.
+		 * Collapses in tandem with  <code>paragraphSpaceBefore</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paragraphSpaceAfter():*;
+
+		/**
+		 * Alignment of lines in the paragraph relative to the container.
+		 * <code>TextAlign.LEFT</code> aligns lines along the left edge of the container. <code>TextAlign.RIGHT</code> aligns on the right edge. <code>TextAlign.CENTER</code> positions the line equidistant from the left and right edges. <code>TextAlign.JUSTIFY</code> spreads the lines out so they fill the space. <code>TextAlign.START</code> is equivalent to setting left in left-to-right text, or right in right-to-left text. <code>TextAlign.END</code> is equivalent to setting right in left-to-right text, or left in right-to-left text.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		function get textAlign():*;
+
+		/**
+		 * Alignment of the last (or only) line in the paragraph relative to the container in justified text.
+		 * If <code>textAlign</code> is set to <code>TextAlign.JUSTIFY</code>, <code>textAlignLast</code> specifies how the last line (or only line, if this is a one line block) is aligned. Values are similar to <code>textAlign</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		function get textAlignLast():*;
+
+		/**
+		 * Specifies options for justifying text.
+		 * Default value is <code>TextJustify.INTER_WORD</code>, meaning that extra space is added to the space characters. <code>TextJustify.DISTRIBUTE</code> adds extra space to space characters and between individual letters. Used only in conjunction with a <code>justificationRule</code> value of <code>JustificationRule.SPACE</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextJustify.INTER_WORD, flashx.textLayout.formats.TextJustify.DISTRIBUTE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of INTER_WORD.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextJustify
+		 */
+		function get textJustify():*;
+
+		/**
+		 * Rule used to justify text in a paragraph.
+		 * Default value is <code>FormatValue.AUTO</code>, which justifies text based on the paragraph's <code>locale</code> property. For all languages except Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustificationRule.SPACE</code>, which adds extra space to the space characters.  For Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustficationRule.EAST_ASIAN</code>. In part, justification changes the spacing of punctuation. In Roman text the comma and Japanese periods take a full character's width but in East Asian text only half of a character's width. Also, in the East Asian text the spacing between sequential punctuation marks becomes tighter, obeying traditional East Asian typographic conventions. Note, too, in the example below the leading that is applied to the second line of the paragraphs. In the East Asian version, the last two lines push left. In the Roman version, the second and following lines push left.<p><img src='../../../images/textLayout_justificationrule.png' alt='justificationRule' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.JustificationRule.EAST_ASIAN, flashx.textLayout.formats.JustificationRule.SPACE, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.JustificationRule
+		 */
+		function get justificationRule():*;
+
+		/**
+		 * The style used for justification of the paragraph. Used only in conjunction with a <code>justificationRule</code> setting of <code>JustificationRule.EAST_ASIAN</code>.
+		 * Default value of <code>FormatValue.AUTO</code> is resolved to <code>JustificationStyle.PUSH_IN_KINSOKU</code> for all locales.  The constants defined by the JustificationStyle class specify options for handling kinsoku characters, which are Japanese characters that cannot appear at either the beginning or end of a line. If you want looser text, specify <code>JustificationStyle.PUSH-OUT-ONLY</code>. If you want behavior that is like what you get with the  <code>justificationRule</code> of <code>JustificationRule.SPACE</code>, use <code>JustificationStyle.PRIORITIZE-LEAST-ADJUSTMENT</code>.
+		 * <p>Legal values are flash.text.engine.JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT, flash.text.engine.JustificationStyle.PUSH_IN_KINSOKU, flash.text.engine.JustificationStyle.PUSH_OUT_ONLY, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.JustificationStyle
+		 */
+		function get justificationStyle():*;
+
+		/**
+		 * Specifies the default bidirectional embedding level of the text in the text block. 
+		 * Left-to-right reading order, as in Latin-style scripts, or right-to-left reading order, as in Arabic or Hebrew. This property also affects column direction when it is applied at the container level. Columns can be either left-to-right or right-to-left, just like text. Below are some examples:<p><img src='../../../images/textLayout_direction.gif' alt='direction' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.Direction.LTR, flashx.textLayout.formats.Direction.RTL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of LTR.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.Direction
+		 */
+		function get direction():*;
+
+		/**
+		 * Specifies the tab stops associated with the paragraph.
+		 * Setters can take an array of flashx.textLayout.formats.TabStopFormat, a condensed string representation, undefined, or <code>FormatValue.INHERIT</code>. The condensed string representation is always converted into an array of flashx.textLayout.formats.TabStopFormat. <p>The string-based format is a list of tab stops, where each tab stop is delimited by one or more spaces.</p><p>A tab stop takes the following form: &lt;alignment type&gt;&lt;alignment position&gt;|&lt;alignment token&gt;.</p><p>The alignment type is a single character, and can be S, E, C, or D (or lower-case equivalents). S or s for start, E or e for end, C or c for center, D or d for decimal. The alignment type is optional, and if its not specified will default to S.</p><p>The alignment position is a Number, and is specified according to FXG spec for Numbers (decimal or scientific notation). The alignment position is required.</p><p>The vertical bar is used to separate the alignment position from the alignment token, and should only be present if the alignment token is present.</p><p> The alignment token is optional if the alignment type is D, and should not be present if the alignment type is anything other than D. The alignment token may be any sequence of characters terminated by the space that ends the tab stop (for the last tab stop, the terminating space is optional; end of alignment token is implied). A space may be part of the alignment token if it is escaped with a backslash (\ ). A backslash may be part of the alignment token if it is escaped with another backslash (\\). If the alignment type is D, and the alignment token is not specified, it will take on the default value of null.</p><p>If no tab stops are specified, a tab action defaults to the end of the line.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get tabStops():*;
+
+		/**
+		 * Specifies the leading model, which is a combination of leading basis and leading direction.
+		 * Leading basis is the baseline to which the <code>lineHeight</code> property refers. Leading direction determines whether the <code>lineHeight</code> property refers to the distance of a line's baseline from that of the line before it or the line after it. The default value of <code>FormatValue.AUTO</code> is resolved based on the paragraph's <code>locale</code> property.  For Japanese and Chinese, it is <code>LeadingModel.IDEOGRAPHIC_TOP_DOWN</code> and for all others it is <code>LeadingModel.ROMAN_UP</code>.<p><strong>Leading Basis:</strong></p><p><img src='../../../images/textLayout_LB1.png' alt='leadingBasis1' />    <img src='../../../images/textLayout_LB2.png' alt='leadingBasis2' />    <img src='../../../images/textLayout_LB3.png' alt='leadingBasis3' /></p><p><strong>Leading Direction:</strong></p><p><img src='../../../images/textLayout_LD1.png' alt='leadingDirection1' />    <img src='../../../images/textLayout_LD2.png' alt='leadingDirection2' />    <img src='../../../images/textLayout_LD3.png' alt='leadingDirection3' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.LeadingModel.ROMAN_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_DOWN, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_DOWN, flashx.textLayout.formats.LeadingModel.APPROXIMATE_TEXT_FIELD, flashx.textLayout.formats.LeadingModel.ASCENT_DESCENT_UP, flashx.textLayout.formats.LeadingModel.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LeadingModel
+		 */
+		function get leadingModel():*;
+
+		/**
+		 * Specifies the amount of gutter space, in pixels, to leave between the columns (adopts default value if undefined during cascade).
+		 * Value is a Number
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 20.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get columnGap():*;
+
+		/**
+		 * Left inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the left edge of the container and the text.  Value is a Number.<p> With vertical text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the end of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paddingLeft():*;
+
+		/**
+		 * Top inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the top edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paddingTop():*;
+
+		/**
+		 * Right inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the right edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paddingRight():*;
+
+		/**
+		 * Botttom inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the bottom edge of the container and the text.  Value is a Number. <p> With horizontal text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the bottom of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		function get paddingBottom():*;
+
+		/**
+		 * Number of text columns (adopts default value if undefined during cascade).
+		 * The column number overrides the  other column settings. Value is an integer, or <code>FormatValue.AUTO</code> if unspecified. If <code>columnCount</code> is not specified,<code>columnWidth</code> is used to create as many columns as can fit in the container.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and from ints from 1 to 50.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		function get columnCount():*;
+
+		/**
+		 * Column width in pixels (adopts default value if undefined during cascade).
+		 * If you specify the width of the columns, but not the count, TextLayout will create as many columns of that width as possible, given the  container width and <code>columnGap</code> settings. Any remainder space is left after the last column. Value is a Number.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 8000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		function get columnWidth():*;
+
+		/**
+		 * Specifies the baseline position of the first line in the container. Which baseline this property refers to depends on the container-level locale.  For Japanese and Chinese, it is <code>TextBaseline.IDEOGRAPHIC_BOTTOM</code>; for all others it is <code>TextBaseline.ROMAN</code>.
+		 * The offset from the top inset (or right inset if <code>blockProgression</code> is RL) of the container to the baseline of the first line can be either <code>BaselineOffset.ASCENT</code>, meaning equal to the ascent of the line, <code>BaselineOffset.LINE_HEIGHT</code>, meaning equal to the height of that first line, or any fixed-value number to specify an absolute distance. <code>BaselineOffset.AUTO</code> aligns the ascent of the line with the container top inset.<p><img src='../../../images/textLayout_FBO1.png' alt='firstBaselineOffset1' /><img src='../../../images/textLayout_FBO2.png' alt='firstBaselineOffset2' /><img src='../../../images/textLayout_FBO3.png' alt='firstBaselineOffset3' /><img src='../../../images/textLayout_FBO4.png' alt='firstBaselineOffset4' /></p>
+		 * <p>Legal values as a string are flashx.textLayout.formats.BaselineOffset.AUTO, flashx.textLayout.formats.BaselineOffset.ASCENT, flashx.textLayout.formats.BaselineOffset.LINE_HEIGHT, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineOffset
+		 */
+		function get firstBaselineOffset():*;
+
+		/**
+		 * Vertical alignment or justification (adopts default value if undefined during cascade).
+		 * Determines how TextFlow elements align within the container.
+		 * <p>Legal values are flashx.textLayout.formats.VerticalAlign.TOP, flashx.textLayout.formats.VerticalAlign.MIDDLE, flashx.textLayout.formats.VerticalAlign.BOTTOM, flashx.textLayout.formats.VerticalAlign.JUSTIFY, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TOP.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.VerticalAlign
+		 */
+		function get verticalAlign():*;
+
+		/**
+		 * Specifies a vertical or horizontal progression of line placement.
+		 * Lines are either placed top-to-bottom (<code>BlockProgression.TB</code>, used for horizontal text) or right-to-left (<code>BlockProgression.RL</code>, used for vertical text).
+		 * <p>Legal values are flashx.textLayout.formats.BlockProgression.RL, flashx.textLayout.formats.BlockProgression.TB, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of TB.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BlockProgression
+		 */
+		function get blockProgression():*;
+
+		/**
+		 * Controls word wrapping within the container (adopts default value if undefined during cascade).
+		 * Text in the container may be set to fit the width of the container (<code>LineBreak.TO_FIT</code>), or can be set to break only at explicit return or line feed characters (<code>LineBreak.EXPLICIT</code>).
+		 * <p>Legal values are flashx.textLayout.formats.LineBreak.EXPLICIT, flashx.textLayout.formats.LineBreak.TO_FIT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TO_FIT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LineBreak
+		 */
+		function get lineBreak():*;
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/JustificationRule.as b/textLayout_core/src/flashx/textLayout/formats/JustificationRule.as
new file mode 100755
index 0000000..00b7769
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/JustificationRule.as
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>justificationRule</code> property
+	 *  of the TextLayoutFormat class. Default value is SPACE, which accomplishes justification by adding 
+	 *  extra space to the space characters. When you use EAST_ASIAN, Japanese style leading is employed, which 
+	 *  applies bottom-down as opposed to top-up, which is used in Roman text. The spacing of punctuation is also 
+	 *  different. In the Roman version, the comma and Japanese periods take a full character's width but only half 
+	 *  in East Asian. Additionally, the spacing between sequential punctuation marks becomes tighter, obeying traditional 
+	 *  East Asian typographic conventions. Also note the leading, applied to the second line of the paragraphs in the 
+	 *  example below. In the East Asian version, the last two lines push left. In the Roman version, the second and 
+	 *  following lines push left.
+	 *  <p><img src="../../../images/textLayout_justificationrule.png" alt="justificationRule" /></p>
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see TextLayoutFormat#justificationRule
+	 */
+	public final class JustificationRule
+	{
+		/** Specifies East Asian justification rules. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const EAST_ASIAN:String = "eastAsian";
+		
+		/** Specifies justification for Latin and other horizontal scripts that divide words using spaces. 
+		 *  Use this value for everything except East Asian text.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const SPACE:String = "space";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/LeadingModel.as b/textLayout_core/src/flashx/textLayout/formats/LeadingModel.as
new file mode 100755
index 0000000..d26c362
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/LeadingModel.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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>leadingModel</code> property
+	 *  of the <code>TextLayoutFormat</code> class, composed of valid combinations of leading basis and leading direction.
+	 *  Leading basis describes which baselines determine the leading (or <code>lineHeight</code>) of lines in a paragraph.
+	 *  Leading direction specifies whether the <code>lineHeight</code> property refers to the distance of a line's 
+	 *  baseline from that of the line before it or the line after it. 
+	 *  <p>
+	 *  <img src="../../../images/textLayout_baselines.jpg" alt="baselines" border="0"/>
+	 *  <img src="../../../images/textLayout_LD1.jpg" alt="leadingDirection_1" border="0"/>
+	 *  <img src="../../../images/textLayout_LD2.jpg" alt="leadingDirection_2" border="0"/>
+	 *  <img src="../../../images/textLayout_LD3.jpg" alt="leadingDirection_3" border="0"/>
+	 *  </p>
+	 *  @playerversion Flash 10
+	 *  @playerversion AIR 1.5
+	 *  @langversion 3.0 
+	 * 
+	 *  @see TextLayoutFormat#leadingModel
+	 *  @see TextLayoutFormat#lineHeight
+	 *  @see flash.text.TextField
+	 *  @see flash.text.engine.TextLine 
+	 */
+	 
+	public final class LeadingModel
+	{
+		/** Specifies that leading basis is ROMAN and leading direction is UP. 
+		 * In other words, <code>lineHeight</code> refers to the distance of a line's Roman baseline from the 
+		 * previous line's Roman baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	  	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const ROMAN_UP:String = "romanUp";
+		
+		/** Specifies that leading basis is IDEOGRAPHIC_TOP and leading direction is UP. 
+		 *  In other words, <code>lineHeight</code> refers to the distance of a line's ideographic top 
+		 *  baseline from the previous line's ideographic top baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const IDEOGRAPHIC_TOP_UP:String = "ideographicTopUp";
+		
+		/** Specifies that leading basis is IDEOGRAPHIC_CENTER and leading direction is UP. 
+		 * In other words, <code>lineHeight</code> refers to the distance of a line's ideographic center 
+		 * baseline from the previous line's ideographic center baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const IDEOGRAPHIC_CENTER_UP:String = "ideographicCenterUp";
+		
+		/** Specifies that leading basis is IDEOGRAPHIC_TOP and leading direction is DOWN.
+		 * In other words, <code>lineHeight</code> refers to the distance of a line's ideographic top baseline 
+		 * from the next line's ideographic top baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const IDEOGRAPHIC_TOP_DOWN:String = "ideographicTopDown";
+		
+		/** Specifies that leading basis is IDEOGRAPHIC_CENTER and leading direction is down.
+		 *  In other words, <code>lineHeight</code> refers to the distance of a line's ideographic center 
+		 *  baseline from the next line's ideographic center baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const IDEOGRAPHIC_CENTER_DOWN:String = "ideographicCenterDown";
+		
+		/** Specifies that leading basis is ASCENT/DESCENT and leading direction is UP. 
+		 *  In other words, <code>lineHeight</code> refers to the distance of a line's ascent baseline from the 
+		 *  previous line's descent baseline.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	  	 * @langversion 3.0 
+	 	 */
+	 	 
+		public static const ASCENT_DESCENT_UP:String = "ascentDescentUp";
+		
+		/** Specifies that leading model is chosen automatically based on the paragraph's <code>locale</code> property.  
+		 * For Japanese and Chinese, it is IDEOGRAPHIC_TOP_DOWN and for all others it is ROMAN_UP.
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	 * 
+	 	 * #IDEOGRAPHIC_TOP_DOWN
+	 	 * #ROMAN_UP
+	 	 */
+	 	 
+		public static const AUTO:String = "auto";
+		
+		/** Specifies a leading model that approximates the line spacing behavior of <code>TextField</code>.
+		 * It is similar to <code>ASCENT_DESCENT_UP</code> in that <code>lineHeight</code> refers to the 
+		 * distance of a line's ascent baseline from the previous line's descent baseline. However, baseline 
+		 * positions approximate those determined by <code>TextField</code>, rather than using metrics 
+		 * offered by <code>TextLine</code>.  
+		 *
+		 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public static const APPROXIMATE_TEXT_FIELD:String = "approximateTextField";
+		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/LineBreak.as b/textLayout_core/src/flashx/textLayout/formats/LineBreak.as
new file mode 100755
index 0000000..9708916
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/LineBreak.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/** Defines values for setting the <code>lineBreak</code> property of <code>TextLayoutFormat</code> to
+	 *  specify how lines are broken within wrapping text.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * @see TextLayoutFormat#linebreak
+	 */
+	public final class LineBreak
+	{
+		/** Specifies that lines wrap to fit the container width. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	  	 * @langversion 3.0 
+		 */
+		 
+		public static const TO_FIT:String = "toFit";
+		
+		/** Specifies that lines break only at explicit return or line feed characters. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const EXPLICIT:String = "explicit";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/TLFTypographicCase.as b/textLayout_core/src/flashx/textLayout/formats/TLFTypographicCase.as
new file mode 100755
index 0000000..3adbdc6
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TLFTypographicCase.as
@@ -0,0 +1,79 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for the <code>typographicCase</code> property of the TextLayoutFormat
+	 *  class. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * 
+	 * @see TextLayoutFormat#typographicCase
+	 */
+	public final class TLFTypographicCase
+	{
+		/** Specifies default typographic case -- no special features applied. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+ 		public static const DEFAULT:String = "default";
+ 		
+		/** Converts all lowercase characters to uppercase, then applies small caps to only the 
+		 * characters that the conversion changed. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+  	 	public static const LOWERCASE_TO_SMALL_CAPS:String = "lowercaseToSmallCaps";
+  	 	
+  	 	/** Specifies that all characters use lowercase glyphs on output. 
+  	 	 *
+  	 	 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+ 	 	public static const LOWERCASE:String = "lowercase";
+
+		/** Specifies that uppercase characters use small-caps glyphs on output. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+ 	 	public static const CAPS_TO_SMALL_CAPS:String = "capsToSmallCaps";
+
+		/** Specifies that all characters use uppercase glyphs on output.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+ 	 	public static const UPPERCASE:String = "uppercase";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/TabStopFormat.as b/textLayout_core/src/flashx/textLayout/formats/TabStopFormat.as
new file mode 100755
index 0000000..2cc59aa
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TabStopFormat.as
@@ -0,0 +1,374 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	import flashx.textLayout.debug.Debugging
+	import flashx.textLayout.debug.assert
+	import flashx.textLayout.property.*
+	import flashx.textLayout.tlf_internal
+	use namespace tlf_internal
+	import flash.text.engine.TabAlignment
+	/**
+	 * The TabStopFormat class represents the properties of a tab stop in a paragraph. You can set the <code>TextLayoutFormat.tabstops</code> property to an array of TabStopFormat objects.
+	 * @includeExample examples\TabStopFormat_example.as -noswf
+	 * @see flashx.textLayout.elements.TabElement 
+	 * @see flashx.textLayout.formats.TextLayoutFormat#tabStops
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public class TabStopFormat implements ITabStopFormat
+	{
+		/** @private */
+		static private var _positionProperty:NumberProperty = new NumberProperty("position",0,false,Category.TABSTOP,0,10000); 		/** @private */
+		static private var _alignmentProperty:EnumStringProperty = new EnumStringProperty(
+			"alignment",flash.text.engine.TabAlignment.START,false,Category.TABSTOP
+			,flash.text.engine.TabAlignment.START
+			,flash.text.engine.TabAlignment.CENTER
+			,flash.text.engine.TabAlignment.END
+			,flash.text.engine.TabAlignment.DECIMAL
+		);
+		/** @private */
+		static private var _decimalAlignmentTokenProperty:StringProperty = new StringProperty("decimalAlignmentToken",null,false,Category.TABSTOP);
+
+		/** @private */
+		static tlf_internal function get positionProperty():NumberProperty
+		{ return _positionProperty; }
+		/** @private */
+		static tlf_internal function get alignmentProperty():EnumStringProperty
+		{ return _alignmentProperty; }
+		/** @private */
+		static tlf_internal function get decimalAlignmentTokenProperty():StringProperty
+		{ return _decimalAlignmentTokenProperty; }
+
+		static private var _description:Object = {
+			  position:_positionProperty
+			, alignment:_alignmentProperty
+			, decimalAlignmentToken:_decimalAlignmentTokenProperty
+		}
+
+		/** Property descriptions accessible by name. @private */
+		static tlf_internal function get description():Object
+		{ return _description; }
+
+		/** @private */
+		static private var _emptyTabStopFormat:ITabStopFormat;
+		/**
+		 * Returns an ITabStopFormat instance with all properties set to <code>undefined</code>.
+		 * @private
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static tlf_internal function get emptyTabStopFormat():ITabStopFormat
+		{
+			if (_emptyTabStopFormat == null)
+				_emptyTabStopFormat = new TabStopFormat();
+			return _emptyTabStopFormat;
+		}
+
+
+		private var _position:*;
+		private var _alignment:*;
+		private var _decimalAlignmentToken:*;
+
+		/**
+		 * The position of the tab stop, in pixels, relative to the start of the line.
+		 * <p>Legal values are numbers from 0 to 10000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * @see FormatValue#INHERIT
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get position():*
+		{ return _position; }
+		public function set position(newValue:*):void
+		{ _position = _positionProperty.setHelper(_position,newValue); }
+
+		/**
+		 * The tab alignment for this tab stop. 
+		 * <p>Legal values are flash.text.engine.TabAlignment.START, flash.text.engine.TabAlignment.CENTER, flash.text.engine.TabAlignment.END, flash.text.engine.TabAlignment.DECIMAL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of START.</p>
+		 * @see FormatValue#INHERIT
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TabAlignment
+		 */
+		public function get alignment():*
+		{ return _alignment; }
+		public function set alignment(newValue:*):void
+		{ _alignment = _alignmentProperty.setHelper(_alignment,newValue); }
+
+		/**
+		 * The alignment token to be used if the alignment is DECIMAL.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get decimalAlignmentToken():*
+		{ return _decimalAlignmentToken; }
+		public function set decimalAlignmentToken(newValue:*):void
+		{ _decimalAlignmentToken = _decimalAlignmentTokenProperty.setHelper(_decimalAlignmentToken,newValue); }
+
+		/**
+		 * Creates a new TabStopFormat object. All settings are empty or, optionally, are initialized from the
+		 * supplied <code>initialValues</code> object.
+		 * 
+		 * @param initialValues optional instance from which to copy initial values.
+		 * 
+		 * @see #defaultFormat
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TabStopFormat(initialValues:ITabStopFormat = null)
+		{
+			if (initialValues)
+				apply(initialValues)
+		}
+
+		/**
+		 * Copies TabStopFormat settings from the <code>values</code> ITabStopFormat instance into this TabStopFormat object.
+		 * If <code>values</code> is <code>null</code>, this TabStopFormat object is initialized with undefined values for all properties.
+		 * @param values optional instance from which to copy values.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function copy(values:ITabStopFormat):void
+		{
+			 if (values == null)
+				values = emptyTabStopFormat;
+			this.position = values.position;
+			this.alignment = values.alignment;
+			this.decimalAlignmentToken = values.decimalAlignmentToken;
+		}
+
+		/**
+		 * Concatenates the values of properties in the <code>incoming</code> ITabStopFormat instance
+		 * with the values of this TabStopFormat object. In this (the receiving) TabStopFormat object, properties whose values are <code>FormatValue.INHERIT</code>,
+		 * and inheriting properties whose values are <code>undefined</code> will get new values from the <code>incoming</code> object.
+		 * Non-inheriting properties whose values are <code>undefined</code> will get their default values.
+		 * All other property values will remain unmodified.
+		 * 
+		 * @param incoming instance from which values are concatenated.
+		 * @see flashx.textLayout.formats.FormatValue#INHERIT
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function concat(incoming:ITabStopFormat):void
+		{
+			this.position = _positionProperty.concatHelper(this.position, incoming.position);
+			this.alignment = _alignmentProperty.concatHelper(this.alignment, incoming.alignment);
+			this.decimalAlignmentToken = _decimalAlignmentTokenProperty.concatHelper(this.decimalAlignmentToken, incoming.decimalAlignmentToken);
+		}
+
+		/**
+		 * Concatenates the values of properties in the <code>incoming</code> ITabStopFormat instance
+		 * with the values of this TabStopFormat object. In this (the receiving) TabStopFormat object, properties whose values are <code>FormatValue.INHERIT</code>,
+		 * and inheriting properties whose values are <code>undefined</code> will get new values from the <code>incoming</code> object.
+		 * All other property values will remain unmodified.
+		 * 
+		 * @param incoming instance from which values are concatenated.
+		 * @see flashx.textLayout.formats.FormatValue#INHERIT
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function concatInheritOnly(incoming:ITabStopFormat):void
+		{
+			this.position = _positionProperty.concatInheritOnlyHelper(this.position, incoming.position);
+			this.alignment = _alignmentProperty.concatInheritOnlyHelper(this.alignment, incoming.alignment);
+			this.decimalAlignmentToken = _decimalAlignmentTokenProperty.concatInheritOnlyHelper(this.decimalAlignmentToken, incoming.decimalAlignmentToken);
+		}
+
+		/**
+		 * Replaces property values in this TabStopFormat object with the values of properties that are set in
+		 * the <code>incoming</code> ITabStopFormat instance. Properties that are <code>undefined</code> in the <code>incoming</code>
+		 * ITabStopFormat instance are not changed in this object.
+		 * 
+		 * @param incoming instance whose property values are applied to this TabStopFormat object.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function apply(incoming:ITabStopFormat):void
+		{
+			var val:*;
+
+			if ((val = incoming.position) !== undefined)
+				this.position = val;
+			if ((val = incoming.alignment) !== undefined)
+				this.alignment = val;
+			if ((val = incoming.decimalAlignmentToken) !== undefined)
+				this.decimalAlignmentToken = val;
+		}
+
+		/**
+		 * Compares properties in ITabStopFormat instance <code>p1</code> with properties in ITabStopFormat instance <code>p2</code>
+		 * and returns <code>true</code> if all properties match.
+		 * 
+		 * @param p1 instance to compare to <code>p2</code>.
+		 * @param p2 instance to compare to <code>p1</code>.
+		 * 
+		 * @return true if all properties match, false otherwise.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isEqual(p1:ITabStopFormat,p2:ITabStopFormat):Boolean
+		{
+			if (p1 == null)
+				p1 = emptyTabStopFormat;
+			if (p2 == null)
+				p2 = emptyTabStopFormat;
+			if (p1 == p2)
+				return true;
+
+			if (!_positionProperty.equalHelper(p1.position, p2.position))
+				return false;
+			if (!_alignmentProperty.equalHelper(p1.alignment, p2.alignment))
+				return false;
+			if (!_decimalAlignmentTokenProperty.equalHelper(p1.decimalAlignmentToken, p2.decimalAlignmentToken))
+				return false;
+
+			return true;
+		}
+
+		/**
+		 * Sets properties in this TabStopFormat object to <code>undefined</code> if they match those in the <code>incoming</code>
+		 * ITabStopFormat instance.
+		 * 
+		 * @param incoming instance against which to compare this TabStopFormat object's property values.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function removeMatching(incoming:ITabStopFormat):void
+		{
+			if (incoming == null)
+				return;
+
+			if (_positionProperty.equalHelper(this.position, incoming.position))
+				this.position = undefined;
+			if (_alignmentProperty.equalHelper(this.alignment, incoming.alignment))
+				this.alignment = undefined;
+			if (_decimalAlignmentTokenProperty.equalHelper(this.decimalAlignmentToken, incoming.decimalAlignmentToken))
+				this.decimalAlignmentToken = undefined;
+		}
+
+		/**
+		 * Sets properties in this TabStopFormat object to <code>undefined</code> if they do not match those in the
+		 * <code>incoming</code> ITabStopFormat instance.
+		 * 
+		 * @param incoming instance against which to compare this TabStopFormat object's property values.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function removeClashing(incoming:ITabStopFormat):void
+		{
+			if (incoming == null)
+				return;
+
+			if (!_positionProperty.equalHelper(this.position, incoming.position))
+				this.position = undefined;
+			if (!_alignmentProperty.equalHelper(this.alignment, incoming.alignment))
+				this.alignment = undefined;
+			if (!_decimalAlignmentTokenProperty.equalHelper(this.decimalAlignmentToken, incoming.decimalAlignmentToken))
+				this.decimalAlignmentToken = undefined;
+		}
+
+		/**
+		 * Gets the TabStopFormat hash
+		 * @param seed seed value for the hash algorithm
+		 * @return the TabStopFormat hash
+		 * @private
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		tlf_internal function hash(seed:uint):uint
+		{
+			var hash:uint = seed;
+
+			if (_position)
+				hash = _positionProperty.hash(_position, hash);
+			if (_alignment)
+				hash = _alignmentProperty.hash(_alignment, hash);
+			if (_decimalAlignmentToken)
+				hash = _decimalAlignmentTokenProperty.hash(_decimalAlignmentToken, hash);
+
+			return hash;
+		}
+
+		static private var _defaults:TabStopFormat;
+		/**
+		 * Returns a TabStopFormat object with default settings.
+		 * This function always returns the same object.
+		 * 
+		 * @return a singleton instance of ITabStopFormat that is populated with default values.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function get defaultFormat():ITabStopFormat
+		{
+			if (_defaults == null)
+			{
+				_defaults = new TabStopFormat();
+				Property.defaultsAllHelper(_description,_defaults);
+				_defaultFormatHash = _defaults.hash(0);
+			}
+			return _defaults;
+		}
+		static private var _defaultFormatHash:uint;
+		/** @private */
+		static tlf_internal function getDefaultFormatHash():uint
+		{
+			defaultFormat;
+			return _defaultFormatHash;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/TabStopFormatInc.as b/textLayout_core/src/flashx/textLayout/formats/TabStopFormatInc.as
new file mode 100755
index 0000000..4a19f2f
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TabStopFormatInc.as
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+		public function get position():*
+		{
+			return _tabStopFormatValueHolder ? _tabStopFormatValueHolder.position : undefined;
+		}
+		public function set position(positionValue:*):void
+		{
+			writableTabStopFormatValueHolder().position = positionValue;
+			tabStopFormatChanged();
+		}
+
+		/**
+		 * TabStopFormat:
+		 * The tab alignment for this tab stop. 
+		 * <p>Legal values are flash.text.engine.TabAlignment.START, flash.text.engine.TabAlignment.CENTER, flash.text.engine.TabAlignment.END, flash.text.engine.TabAlignment.DECIMAL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of START.</p>
+		 * @see FormatValue#INHERIT
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TabAlignment
+		 */
+		public function get alignment():*
+		{
+			return _tabStopFormatValueHolder ? _tabStopFormatValueHolder.alignment : undefined;
+		}
+		public function set alignment(alignmentValue:*):void
+		{
+			writableTabStopFormatValueHolder().alignment = alignmentValue;
+			tabStopFormatChanged();
+		}
+
+		/**
+		 * TabStopFormat:
+		 * The alignment token to be used if the alignment is DECIMAL.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get decimalAlignmentToken():*
+		{
+			return _tabStopFormatValueHolder ? _tabStopFormatValueHolder.decimalAlignmentToken : undefined;
+		}
+		public function set decimalAlignmentToken(decimalAlignmentTokenValue:*):void
+		{
+			writableTabStopFormatValueHolder().decimalAlignmentToken = decimalAlignmentTokenValue;
+			tabStopFormatChanged();
+		}
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextAlign.as b/textLayout_core/src/flashx/textLayout/formats/TextAlign.as
new file mode 100755
index 0000000..b53a0dc
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextAlign.as
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>textAlign</code> and <code>textAlignLast</code> properties
+	 *  of the TextLayoutFormat class. The values describe the alignment of lines in the paragraph relative to the 
+	 *  container.
+	 *
+	 * @includeExample examples\TextAlignExample.as -noswf
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 * @see TextLayoutFormat#textAlign 
+	 * @see TextLayoutFormat#textAlignLast 
+	 */
+	public final class TextAlign
+	{
+		/** Specifies start edge alignment - text is aligned to match the writing order. Equivalent to setting 
+		 * left in left-to-right text, or right in right-to-left text.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const START:String = "start";
+		
+		/** Specifies end edge alignment - text is aligned opposite from the writing order. Equivalent to 
+		 *  specifying right in left-to-right text, or left in right-to-left text. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const END:String = "end";
+		
+		/** Specifies left edge alignment. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const LEFT:String = "left";
+		
+		/** Specifies right edge alignment. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const RIGHT:String = "right";
+		
+		/** Specifies center alignment within the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const CENTER:String = "center";
+		
+		/** Specifies that text is justified within the lines so they fill the container space.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const JUSTIFY:String = "justify";
+		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextDecoration.as b/textLayout_core/src/flashx/textLayout/formats/TextDecoration.as
new file mode 100755
index 0000000..260b0c8
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextDecoration.as
@@ -0,0 +1,53 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for the <code>textDecoration</code> property
+	 *  of the TextLayoutFormat class. The values specify either normal text, with no decoration,
+	 *  or underline.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  
+	 * @see TextLayoutFormat#textDecoration
+	 */
+	 
+	public final class TextDecoration
+	{
+		/** Specifies normal text - no decoration applied 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const NONE:String = "none";
+		
+		/** Specifies that text is underlined. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const UNDERLINE:String = "underline";
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextJustify.as b/textLayout_core/src/flashx/textLayout/formats/TextJustify.as
new file mode 100755
index 0000000..6e58e31
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextJustify.as
@@ -0,0 +1,55 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>textJustify</code> property of the TextLayoutFormat class. 
+	 *  Default value is INTER_WORD, meaning that extra space in justification is added to the space characters.
+	 *  DISTRIBUTE specifies that extra space is added both to space characters and between individual
+	 *  letters. Use these values only when setting <code>justificationRule</code> to SPACE.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 *
+	 * @see TextLayoutFormat#textJustify
+	 * @see TextLayoutFormat#justificationRule
+	 */
+	public final class TextJustify
+	{
+		/** Specifies that justification is to add space both to space characters and 
+		 * between individual letters.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const DISTRIBUTE:String = "distribute";
+		
+		/** Specifies that justification is to add space to space characters. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const INTER_WORD:String = "interWord";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormat.as b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormat.as
new file mode 100755
index 0000000..f5499a3
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormat.as
@@ -0,0 +1,2482 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	import flashx.textLayout.debug.Debugging
+	import flashx.textLayout.debug.assert
+	import flashx.textLayout.property.*
+	import flashx.textLayout.tlf_internal
+	use namespace tlf_internal
+	import flashx.textLayout.formats.BackgroundColor
+	import flash.text.engine.BreakOpportunity
+	import flash.text.engine.DigitCase
+	import flash.text.engine.DigitWidth
+	import flash.text.engine.TextBaseline
+	import flash.text.engine.Kerning
+	import flash.text.engine.LigatureLevel
+	import flash.text.engine.TextBaseline
+	import flashx.textLayout.formats.TLFTypographicCase
+	import flashx.textLayout.formats.TextDecoration
+	import flash.text.engine.FontWeight
+	import flash.text.engine.FontPosture
+	import flashx.textLayout.formats.WhiteSpaceCollapse
+	import flash.text.engine.RenderingMode
+	import flash.text.engine.CFFHinting
+	import flash.text.engine.FontLookup
+	import flash.text.engine.TextRotation
+	import flashx.textLayout.formats.TextAlign
+	import flashx.textLayout.formats.TextAlign
+	import flashx.textLayout.formats.TextJustify
+	import flashx.textLayout.formats.JustificationRule
+	import flash.text.engine.JustificationStyle
+	import flashx.textLayout.formats.Direction
+	import flashx.textLayout.formats.LeadingModel
+	import flashx.textLayout.formats.FormatValue
+	import flashx.textLayout.formats.FormatValue
+	import flashx.textLayout.formats.BaselineOffset
+	import flashx.textLayout.formats.VerticalAlign
+	import flashx.textLayout.formats.BlockProgression
+	import flashx.textLayout.formats.LineBreak
+	/**
+	 * The TextLayoutFormat class holds all of the text layout properties. These properties affect the format and style of a text flow at the container level, paragraph level, and text level.  Both the ContainerController class and the FlowElement base class have <code>format</code> properties that enable you to assign a TextLayoutFormat instance to them. Assign a TextLayoutFormat object to a container to affect the format of all of the container's content. Assign a TextLayoutFormat object to a FlowElement descendant to specify formatting for that particular element: TextFlow, ParagraphElement, DivElement, SpanElement, InlineGraphicElement, LinkElement, and TCYElement.
+	 * In addition to the <code>format</code> property, these classes also define each of the individual TextLayoutFormat properties so that you can override the setting of a particular style property for that element, if you wish. <p>Because you can set a given style at multiple levels, it is possible to have conflicts. For example, the color of the text at the TextFlow level could be set to black while a SpanElement object sets it to blue. The general rule is that the setting at the lowest level on the text flow tree takes precedence. So if the ligature level is set for a TextFlow instance and also set for a DivElement, the DivElement setting takes precedence. </p><p>Cascading styles refers to the process of adopting styles from a higher level in the text flow if a style value is undefined at a lower level. When a style is undefined on an element at the point it is about to be rendered, it either takes its default value or the value cascades or descends from the value on a parent element. For example, if the transparency (<code>textAlpha</code> property) of the text is undefined on a SpanElement object, but is set on the TextFlow, the value of the <code>TextFlow.textAlpha</code> property cascades to the SpanElement object and is applied to the text for that span. The result of the cascade, or the sum of the styles that is applied to the element, is stored in the element's <code>computedFormat</code> property.</p><p>In the same way, you can apply user styles using the <code>userStyles</code> property of the ContainerController and FlowElement classes. This  property allows you to read or write a dictionary of user styles and apply its settings to a container or a text flow element. The user styles dictionary is an object that consists of <em>stylename-value</em> pairs. Styles specified by the <code>userStyles</code> property take precedence over all others.</p><p>Most styles that are undefined inherit the value of their immediate parent during a cascade. A small number of styles, however, do not inherit their parent's value and take on their default values instead.</p><p><strong>Style properties that adopt their default values, if undefined, include:</strong> <code>backgroundAlpha</code>, <code>backgroundColor</code>, <code>columnCount</code>, <code>columnGap</code>, <code>columnWidth</code>, <code>lineBreak</code>, <code>paddingBottom</code>, <code>paddingLeft</code>, <code>paddingRight</code>, <code>paddingTop</code>, <code>verticalAlign</code>.</p>
+	 * @includeExample examples\TextLayoutFormatExample.as -noswf
+	 * @includeExample examples\TextLayoutFormatExample2.as -noswf
+	 * @see flashx.textLayout.elements.FlowElement#format
+	 * @see flashx.textLayout.factory.TextFlowTextLineFactory
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5 
+	 * @langversion 3.0 
+	 */
+	public class TextLayoutFormat implements ITextLayoutFormat
+	{
+		/** @private */
+		static private var _colorProperty:UintProperty = new UintProperty("color",0,true,Category.CHARACTER);
+		/** @private */
+		static private var _backgroundColorProperty:UintWithEnumProperty = new UintWithEnumProperty(
+			"backgroundColor",flashx.textLayout.formats.BackgroundColor.TRANSPARENT,false,Category.CHARACTER
+			,flashx.textLayout.formats.BackgroundColor.TRANSPARENT
+		);
+		/** @private */
+		static private var _lineThroughProperty:BooleanProperty = new BooleanProperty("lineThrough",false,true,Category.CHARACTER);
+		/** @private */
+		static private var _textAlphaProperty:NumberProperty = new NumberProperty("textAlpha",1,true,Category.CHARACTER,0,1); 		/** @private */
+		static private var _backgroundAlphaProperty:NumberProperty = new NumberProperty("backgroundAlpha",1,false,Category.CHARACTER,0,1); 		/** @private */
+		static private var _fontSizeProperty:NumberProperty = new NumberProperty("fontSize",12,true,Category.CHARACTER,1,720); 		/** @private */
+		static private var _baselineShiftProperty:NumberOrPercentOrEnumProperty = new NumberOrPercentOrEnumProperty("baselineShift",0.0,true,Category.CHARACTER,-1000,1000,"-1000%","1000%"
+			,flashx.textLayout.formats.BaselineShift.SUPERSCRIPT
+			,flashx.textLayout.formats.BaselineShift.SUBSCRIPT
+		);
+		/** @private */
+		static private var _trackingLeftProperty:NumberOrPercentProperty = new NumberOrPercentProperty("trackingLeft",0,true,Category.CHARACTER,-1000,1000,"-1000%","1000%")
+		/** @private */
+		static private var _trackingRightProperty:NumberOrPercentProperty = new NumberOrPercentProperty("trackingRight",0,true,Category.CHARACTER,-1000,1000,"-1000%","1000%")
+		/** @private */
+		static private var _lineHeightProperty:NumberOrPercentProperty = new NumberOrPercentProperty("lineHeight","120%",true,Category.CHARACTER,-720,720,"-1000%","1000%")
+		/** @private */
+		static private var _breakOpportunityProperty:EnumStringProperty = new EnumStringProperty(
+			"breakOpportunity",flash.text.engine.BreakOpportunity.AUTO,true,Category.CHARACTER
+			,flash.text.engine.BreakOpportunity.ALL
+			,flash.text.engine.BreakOpportunity.ANY
+			,flash.text.engine.BreakOpportunity.AUTO
+			,flash.text.engine.BreakOpportunity.NONE
+		);
+		/** @private */
+		static private var _digitCaseProperty:EnumStringProperty = new EnumStringProperty(
+			"digitCase",flash.text.engine.DigitCase.DEFAULT,true,Category.CHARACTER
+			,flash.text.engine.DigitCase.DEFAULT
+			,flash.text.engine.DigitCase.LINING
+			,flash.text.engine.DigitCase.OLD_STYLE
+		);
+		/** @private */
+		static private var _digitWidthProperty:EnumStringProperty = new EnumStringProperty(
+			"digitWidth",flash.text.engine.DigitWidth.DEFAULT,true,Category.CHARACTER
+			,flash.text.engine.DigitWidth.DEFAULT
+			,flash.text.engine.DigitWidth.PROPORTIONAL
+			,flash.text.engine.DigitWidth.TABULAR
+		);
+		/** @private */
+		static private var _dominantBaselineProperty:EnumStringProperty = new EnumStringProperty(
+			"dominantBaseline",flashx.textLayout.formats.FormatValue.AUTO,true,Category.CHARACTER
+			,flashx.textLayout.formats.FormatValue.AUTO
+			,flash.text.engine.TextBaseline.ROMAN
+			,flash.text.engine.TextBaseline.ASCENT
+			,flash.text.engine.TextBaseline.DESCENT
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM
+		);
+		/** @private */
+		static private var _kerningProperty:EnumStringProperty = new EnumStringProperty(
+			"kerning",flash.text.engine.Kerning.AUTO,true,Category.CHARACTER
+			,flash.text.engine.Kerning.ON
+			,flash.text.engine.Kerning.OFF
+			,flash.text.engine.Kerning.AUTO
+		);
+		/** @private */
+		static private var _ligatureLevelProperty:EnumStringProperty = new EnumStringProperty(
+			"ligatureLevel",flash.text.engine.LigatureLevel.COMMON,true,Category.CHARACTER
+			,flash.text.engine.LigatureLevel.MINIMUM
+			,flash.text.engine.LigatureLevel.COMMON
+			,flash.text.engine.LigatureLevel.UNCOMMON
+			,flash.text.engine.LigatureLevel.EXOTIC
+		);
+		/** @private */
+		static private var _alignmentBaselineProperty:EnumStringProperty = new EnumStringProperty(
+			"alignmentBaseline",flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE,true,Category.CHARACTER
+			,flash.text.engine.TextBaseline.ROMAN
+			,flash.text.engine.TextBaseline.ASCENT
+			,flash.text.engine.TextBaseline.DESCENT
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER
+			,flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM
+			,flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE
+		);
+		/** @private */
+		static private var _localeProperty:StringProperty = new StringProperty("locale","en",true,Category.CHARACTER);
+		/** @private */
+		static private var _typographicCaseProperty:EnumStringProperty = new EnumStringProperty(
+			"typographicCase",flashx.textLayout.formats.TLFTypographicCase.DEFAULT,true,Category.CHARACTER
+			,flashx.textLayout.formats.TLFTypographicCase.DEFAULT
+			,flashx.textLayout.formats.TLFTypographicCase.CAPS_TO_SMALL_CAPS
+			,flashx.textLayout.formats.TLFTypographicCase.UPPERCASE
+			,flashx.textLayout.formats.TLFTypographicCase.LOWERCASE
+			,flashx.textLayout.formats.TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS
+		);
+		/** @private */
+		static private var _fontFamilyProperty:StringProperty = new StringProperty("fontFamily","Arial",true,Category.CHARACTER);
+		/** @private */
+		static private var _textDecorationProperty:EnumStringProperty = new EnumStringProperty(
+			"textDecoration",flashx.textLayout.formats.TextDecoration.NONE,true,Category.CHARACTER
+			,flashx.textLayout.formats.TextDecoration.NONE
+			,flashx.textLayout.formats.TextDecoration.UNDERLINE
+		);
+		/** @private */
+		static private var _fontWeightProperty:EnumStringProperty = new EnumStringProperty(
+			"fontWeight",flash.text.engine.FontWeight.NORMAL,true,Category.CHARACTER
+			,flash.text.engine.FontWeight.NORMAL
+			,flash.text.engine.FontWeight.BOLD
+		);
+		/** @private */
+		static private var _fontStyleProperty:EnumStringProperty = new EnumStringProperty(
+			"fontStyle",flash.text.engine.FontPosture.NORMAL,true,Category.CHARACTER
+			,flash.text.engine.FontPosture.NORMAL
+			,flash.text.engine.FontPosture.ITALIC
+		);
+		/** @private */
+		static private var _whiteSpaceCollapseProperty:EnumStringProperty = new EnumStringProperty(
+			"whiteSpaceCollapse",flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE,true,Category.CHARACTER
+			,flashx.textLayout.formats.WhiteSpaceCollapse.PRESERVE
+			,flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE
+		);
+		/** @private */
+		static private var _renderingModeProperty:EnumStringProperty = new EnumStringProperty(
+			"renderingMode",flash.text.engine.RenderingMode.CFF,true,Category.CHARACTER
+			,flash.text.engine.RenderingMode.NORMAL
+			,flash.text.engine.RenderingMode.CFF
+		);
+		/** @private */
+		static private var _cffHintingProperty:EnumStringProperty = new EnumStringProperty(
+			"cffHinting",flash.text.engine.CFFHinting.HORIZONTAL_STEM,true,Category.CHARACTER
+			,flash.text.engine.CFFHinting.NONE
+			,flash.text.engine.CFFHinting.HORIZONTAL_STEM
+		);
+		/** @private */
+		static private var _fontLookupProperty:EnumStringProperty = new EnumStringProperty(
+			"fontLookup",flash.text.engine.FontLookup.DEVICE,true,Category.CHARACTER
+			,flash.text.engine.FontLookup.DEVICE
+			,flash.text.engine.FontLookup.EMBEDDED_CFF
+		);
+		/** @private */
+		static private var _textRotationProperty:EnumStringProperty = new EnumStringProperty(
+			"textRotation",flash.text.engine.TextRotation.AUTO,true,Category.CHARACTER
+			,flash.text.engine.TextRotation.ROTATE_0
+			,flash.text.engine.TextRotation.ROTATE_180
+			,flash.text.engine.TextRotation.ROTATE_270
+			,flash.text.engine.TextRotation.ROTATE_90
+			,flash.text.engine.TextRotation.AUTO
+		);
+		/** @private */
+		static private var _textIndentProperty:NumberProperty = new NumberProperty("textIndent",0,true,Category.PARAGRAPH,-1000,1000); 		/** @private */
+		static private var _paragraphStartIndentProperty:NumberProperty = new NumberProperty("paragraphStartIndent",0,true,Category.PARAGRAPH,0,1000); 		/** @private */
+		static private var _paragraphEndIndentProperty:NumberProperty = new NumberProperty("paragraphEndIndent",0,true,Category.PARAGRAPH,0,1000); 		/** @private */
+		static private var _paragraphSpaceBeforeProperty:NumberProperty = new NumberProperty("paragraphSpaceBefore",0,true,Category.PARAGRAPH,0,1000); 		/** @private */
+		static private var _paragraphSpaceAfterProperty:NumberProperty = new NumberProperty("paragraphSpaceAfter",0,true,Category.PARAGRAPH,0,1000); 		/** @private */
+		static private var _textAlignProperty:EnumStringProperty = new EnumStringProperty(
+			"textAlign",flashx.textLayout.formats.TextAlign.START,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.TextAlign.LEFT
+			,flashx.textLayout.formats.TextAlign.RIGHT
+			,flashx.textLayout.formats.TextAlign.CENTER
+			,flashx.textLayout.formats.TextAlign.JUSTIFY
+			,flashx.textLayout.formats.TextAlign.START
+			,flashx.textLayout.formats.TextAlign.END
+		);
+		/** @private */
+		static private var _textAlignLastProperty:EnumStringProperty = new EnumStringProperty(
+			"textAlignLast",flashx.textLayout.formats.TextAlign.START,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.TextAlign.LEFT
+			,flashx.textLayout.formats.TextAlign.RIGHT
+			,flashx.textLayout.formats.TextAlign.CENTER
+			,flashx.textLayout.formats.TextAlign.JUSTIFY
+			,flashx.textLayout.formats.TextAlign.START
+			,flashx.textLayout.formats.TextAlign.END
+		);
+		/** @private */
+		static private var _textJustifyProperty:EnumStringProperty = new EnumStringProperty(
+			"textJustify",flashx.textLayout.formats.TextJustify.INTER_WORD,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.TextJustify.INTER_WORD
+			,flashx.textLayout.formats.TextJustify.DISTRIBUTE
+		);
+		/** @private */
+		static private var _justificationRuleProperty:EnumStringProperty = new EnumStringProperty(
+			"justificationRule",flashx.textLayout.formats.FormatValue.AUTO,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.JustificationRule.EAST_ASIAN
+			,flashx.textLayout.formats.JustificationRule.SPACE
+			,flashx.textLayout.formats.FormatValue.AUTO
+		);
+		/** @private */
+		static private var _justificationStyleProperty:EnumStringProperty = new EnumStringProperty(
+			"justificationStyle",flashx.textLayout.formats.FormatValue.AUTO,true,Category.PARAGRAPH
+			,flash.text.engine.JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT
+			,flash.text.engine.JustificationStyle.PUSH_IN_KINSOKU
+			,flash.text.engine.JustificationStyle.PUSH_OUT_ONLY
+			,flashx.textLayout.formats.FormatValue.AUTO
+		);
+		/** @private */
+		static private var _directionProperty:EnumStringProperty = new EnumStringProperty(
+			"direction",flashx.textLayout.formats.Direction.LTR,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.Direction.LTR
+			,flashx.textLayout.formats.Direction.RTL
+		);
+		/** @private */
+		static private var _tabStopsProperty:TabStopsProperty = new TabStopsProperty("tabStops",null,true,Category.PARAGRAPH);
+		/** @private */
+		static private var _leadingModelProperty:EnumStringProperty = new EnumStringProperty(
+			"leadingModel",flashx.textLayout.formats.LeadingModel.AUTO,true,Category.PARAGRAPH
+			,flashx.textLayout.formats.LeadingModel.ROMAN_UP
+			,flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_UP
+			,flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_UP
+			,flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_DOWN
+			,flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_DOWN
+			,flashx.textLayout.formats.LeadingModel.APPROXIMATE_TEXT_FIELD
+			,flashx.textLayout.formats.LeadingModel.ASCENT_DESCENT_UP
+			,flashx.textLayout.formats.LeadingModel.AUTO
+		);
+		/** @private */
+		static private var _columnGapProperty:NumberProperty = new NumberProperty("columnGap",20,false,Category.CONTAINER,0,1000); 		/** @private */
+		static private var _paddingLeftProperty:NumberProperty = new NumberProperty("paddingLeft",0,false,Category.CONTAINER,0,1000); 		/** @private */
+		static private var _paddingTopProperty:NumberProperty = new NumberProperty("paddingTop",0,false,Category.CONTAINER,0,1000); 		/** @private */
+		static private var _paddingRightProperty:NumberProperty = new NumberProperty("paddingRight",0,false,Category.CONTAINER,0,1000); 		/** @private */
+		static private var _paddingBottomProperty:NumberProperty = new NumberProperty("paddingBottom",0,false,Category.CONTAINER,0,1000); 		/** @private */
+		static private var _columnCountProperty:IntWithEnumProperty = new IntWithEnumProperty(
+			"columnCount",flashx.textLayout.formats.FormatValue.AUTO,false,Category.CONTAINER,1,50
+			,flashx.textLayout.formats.FormatValue.AUTO
+		);
+		/** @private */
+		static private var _columnWidthProperty:NumberWithEnumProperty = new NumberWithEnumProperty(
+			"columnWidth",flashx.textLayout.formats.FormatValue.AUTO,false,Category.CONTAINER,0,8000
+			,flashx.textLayout.formats.FormatValue.AUTO
+		);
+		/** @private */
+		static private var _firstBaselineOffsetProperty:NumberWithEnumProperty = new NumberWithEnumProperty(
+			"firstBaselineOffset",flashx.textLayout.formats.BaselineOffset.AUTO,true,Category.CONTAINER,0,1000
+			,flashx.textLayout.formats.BaselineOffset.AUTO
+			,flashx.textLayout.formats.BaselineOffset.ASCENT
+			,flashx.textLayout.formats.BaselineOffset.LINE_HEIGHT
+		);
+		/** @private */
+		static private var _verticalAlignProperty:EnumStringProperty = new EnumStringProperty(
+			"verticalAlign",flashx.textLayout.formats.VerticalAlign.TOP,false,Category.CONTAINER
+			,flashx.textLayout.formats.VerticalAlign.TOP
+			,flashx.textLayout.formats.VerticalAlign.MIDDLE
+			,flashx.textLayout.formats.VerticalAlign.BOTTOM
+			,flashx.textLayout.formats.VerticalAlign.JUSTIFY
+		);
+		/** @private */
+		static private var _blockProgressionProperty:EnumStringProperty = new EnumStringProperty(
+			"blockProgression",flashx.textLayout.formats.BlockProgression.TB,true,Category.CONTAINER
+			,flashx.textLayout.formats.BlockProgression.RL
+			,flashx.textLayout.formats.BlockProgression.TB
+		);
+		/** @private */
+		static private var _lineBreakProperty:EnumStringProperty = new EnumStringProperty(
+			"lineBreak",flashx.textLayout.formats.LineBreak.TO_FIT,false,Category.CONTAINER
+			,flashx.textLayout.formats.LineBreak.EXPLICIT
+			,flashx.textLayout.formats.LineBreak.TO_FIT
+		);
+
+		/** @private */
+		static tlf_internal function get colorProperty():UintProperty
+		{ return _colorProperty; }
+		/** @private */
+		static tlf_internal function get backgroundColorProperty():UintWithEnumProperty
+		{ return _backgroundColorProperty; }
+		/** @private */
+		static tlf_internal function get lineThroughProperty():BooleanProperty
+		{ return _lineThroughProperty; }
+		/** @private */
+		static tlf_internal function get textAlphaProperty():NumberProperty
+		{ return _textAlphaProperty; }
+		/** @private */
+		static tlf_internal function get backgroundAlphaProperty():NumberProperty
+		{ return _backgroundAlphaProperty; }
+		/** @private */
+		static tlf_internal function get fontSizeProperty():NumberProperty
+		{ return _fontSizeProperty; }
+		/** @private */
+		static tlf_internal function get baselineShiftProperty():NumberOrPercentOrEnumProperty
+		{ return _baselineShiftProperty; }
+		/** @private */
+		static tlf_internal function get trackingLeftProperty():NumberOrPercentProperty
+		{ return _trackingLeftProperty; }
+		/** @private */
+		static tlf_internal function get trackingRightProperty():NumberOrPercentProperty
+		{ return _trackingRightProperty; }
+		/** @private */
+		static tlf_internal function get lineHeightProperty():NumberOrPercentProperty
+		{ return _lineHeightProperty; }
+		/** @private */
+		static tlf_internal function get breakOpportunityProperty():EnumStringProperty
+		{ return _breakOpportunityProperty; }
+		/** @private */
+		static tlf_internal function get digitCaseProperty():EnumStringProperty
+		{ return _digitCaseProperty; }
+		/** @private */
+		static tlf_internal function get digitWidthProperty():EnumStringProperty
+		{ return _digitWidthProperty; }
+		/** @private */
+		static tlf_internal function get dominantBaselineProperty():EnumStringProperty
+		{ return _dominantBaselineProperty; }
+		/** @private */
+		static tlf_internal function get kerningProperty():EnumStringProperty
+		{ return _kerningProperty; }
+		/** @private */
+		static tlf_internal function get ligatureLevelProperty():EnumStringProperty
+		{ return _ligatureLevelProperty; }
+		/** @private */
+		static tlf_internal function get alignmentBaselineProperty():EnumStringProperty
+		{ return _alignmentBaselineProperty; }
+		/** @private */
+		static tlf_internal function get localeProperty():StringProperty
+		{ return _localeProperty; }
+		/** @private */
+		static tlf_internal function get typographicCaseProperty():EnumStringProperty
+		{ return _typographicCaseProperty; }
+		/** @private */
+		static tlf_internal function get fontFamilyProperty():StringProperty
+		{ return _fontFamilyProperty; }
+		/** @private */
+		static tlf_internal function get textDecorationProperty():EnumStringProperty
+		{ return _textDecorationProperty; }
+		/** @private */
+		static tlf_internal function get fontWeightProperty():EnumStringProperty
+		{ return _fontWeightProperty; }
+		/** @private */
+		static tlf_internal function get fontStyleProperty():EnumStringProperty
+		{ return _fontStyleProperty; }
+		/** @private */
+		static tlf_internal function get whiteSpaceCollapseProperty():EnumStringProperty
+		{ return _whiteSpaceCollapseProperty; }
+		/** @private */
+		static tlf_internal function get renderingModeProperty():EnumStringProperty
+		{ return _renderingModeProperty; }
+		/** @private */
+		static tlf_internal function get cffHintingProperty():EnumStringProperty
+		{ return _cffHintingProperty; }
+		/** @private */
+		static tlf_internal function get fontLookupProperty():EnumStringProperty
+		{ return _fontLookupProperty; }
+		/** @private */
+		static tlf_internal function get textRotationProperty():EnumStringProperty
+		{ return _textRotationProperty; }
+		/** @private */
+		static tlf_internal function get textIndentProperty():NumberProperty
+		{ return _textIndentProperty; }
+		/** @private */
+		static tlf_internal function get paragraphStartIndentProperty():NumberProperty
+		{ return _paragraphStartIndentProperty; }
+		/** @private */
+		static tlf_internal function get paragraphEndIndentProperty():NumberProperty
+		{ return _paragraphEndIndentProperty; }
+		/** @private */
+		static tlf_internal function get paragraphSpaceBeforeProperty():NumberProperty
+		{ return _paragraphSpaceBeforeProperty; }
+		/** @private */
+		static tlf_internal function get paragraphSpaceAfterProperty():NumberProperty
+		{ return _paragraphSpaceAfterProperty; }
+		/** @private */
+		static tlf_internal function get textAlignProperty():EnumStringProperty
+		{ return _textAlignProperty; }
+		/** @private */
+		static tlf_internal function get textAlignLastProperty():EnumStringProperty
+		{ return _textAlignLastProperty; }
+		/** @private */
+		static tlf_internal function get textJustifyProperty():EnumStringProperty
+		{ return _textJustifyProperty; }
+		/** @private */
+		static tlf_internal function get justificationRuleProperty():EnumStringProperty
+		{ return _justificationRuleProperty; }
+		/** @private */
+		static tlf_internal function get justificationStyleProperty():EnumStringProperty
+		{ return _justificationStyleProperty; }
+		/** @private */
+		static tlf_internal function get directionProperty():EnumStringProperty
+		{ return _directionProperty; }
+		/** @private */
+		static tlf_internal function get tabStopsProperty():TabStopsProperty
+		{ return _tabStopsProperty; }
+		/** @private */
+		static tlf_internal function get leadingModelProperty():EnumStringProperty
+		{ return _leadingModelProperty; }
+		/** @private */
+		static tlf_internal function get columnGapProperty():NumberProperty
+		{ return _columnGapProperty; }
+		/** @private */
+		static tlf_internal function get paddingLeftProperty():NumberProperty
+		{ return _paddingLeftProperty; }
+		/** @private */
+		static tlf_internal function get paddingTopProperty():NumberProperty
+		{ return _paddingTopProperty; }
+		/** @private */
+		static tlf_internal function get paddingRightProperty():NumberProperty
+		{ return _paddingRightProperty; }
+		/** @private */
+		static tlf_internal function get paddingBottomProperty():NumberProperty
+		{ return _paddingBottomProperty; }
+		/** @private */
+		static tlf_internal function get columnCountProperty():IntWithEnumProperty
+		{ return _columnCountProperty; }
+		/** @private */
+		static tlf_internal function get columnWidthProperty():NumberWithEnumProperty
+		{ return _columnWidthProperty; }
+		/** @private */
+		static tlf_internal function get firstBaselineOffsetProperty():NumberWithEnumProperty
+		{ return _firstBaselineOffsetProperty; }
+		/** @private */
+		static tlf_internal function get verticalAlignProperty():EnumStringProperty
+		{ return _verticalAlignProperty; }
+		/** @private */
+		static tlf_internal function get blockProgressionProperty():EnumStringProperty
+		{ return _blockProgressionProperty; }
+		/** @private */
+		static tlf_internal function get lineBreakProperty():EnumStringProperty
+		{ return _lineBreakProperty; }
+
+		static private var _description:Object = {
+			  color:_colorProperty
+			, backgroundColor:_backgroundColorProperty
+			, lineThrough:_lineThroughProperty
+			, textAlpha:_textAlphaProperty
+			, backgroundAlpha:_backgroundAlphaProperty
+			, fontSize:_fontSizeProperty
+			, baselineShift:_baselineShiftProperty
+			, trackingLeft:_trackingLeftProperty
+			, trackingRight:_trackingRightProperty
+			, lineHeight:_lineHeightProperty
+			, breakOpportunity:_breakOpportunityProperty
+			, digitCase:_digitCaseProperty
+			, digitWidth:_digitWidthProperty
+			, dominantBaseline:_dominantBaselineProperty
+			, kerning:_kerningProperty
+			, ligatureLevel:_ligatureLevelProperty
+			, alignmentBaseline:_alignmentBaselineProperty
+			, locale:_localeProperty
+			, typographicCase:_typographicCaseProperty
+			, fontFamily:_fontFamilyProperty
+			, textDecoration:_textDecorationProperty
+			, fontWeight:_fontWeightProperty
+			, fontStyle:_fontStyleProperty
+			, whiteSpaceCollapse:_whiteSpaceCollapseProperty
+			, renderingMode:_renderingModeProperty
+			, cffHinting:_cffHintingProperty
+			, fontLookup:_fontLookupProperty
+			, textRotation:_textRotationProperty
+			, textIndent:_textIndentProperty
+			, paragraphStartIndent:_paragraphStartIndentProperty
+			, paragraphEndIndent:_paragraphEndIndentProperty
+			, paragraphSpaceBefore:_paragraphSpaceBeforeProperty
+			, paragraphSpaceAfter:_paragraphSpaceAfterProperty
+			, textAlign:_textAlignProperty
+			, textAlignLast:_textAlignLastProperty
+			, textJustify:_textJustifyProperty
+			, justificationRule:_justificationRuleProperty
+			, justificationStyle:_justificationStyleProperty
+			, direction:_directionProperty
+			, tabStops:_tabStopsProperty
+			, leadingModel:_leadingModelProperty
+			, columnGap:_columnGapProperty
+			, paddingLeft:_paddingLeftProperty
+			, paddingTop:_paddingTopProperty
+			, paddingRight:_paddingRightProperty
+			, paddingBottom:_paddingBottomProperty
+			, columnCount:_columnCountProperty
+			, columnWidth:_columnWidthProperty
+			, firstBaselineOffset:_firstBaselineOffsetProperty
+			, verticalAlign:_verticalAlignProperty
+			, blockProgression:_blockProgressionProperty
+			, lineBreak:_lineBreakProperty
+		}
+
+		/** Property descriptions accessible by name. @private */
+		static tlf_internal function get description():Object
+		{ return _description; }
+
+		/** @private */
+		static private var _emptyTextLayoutFormat:ITextLayoutFormat;
+		/**
+		 * Returns an ITextLayoutFormat instance with all properties set to <code>undefined</code>.
+		 * @private
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static tlf_internal function get emptyTextLayoutFormat():ITextLayoutFormat
+		{
+			if (_emptyTextLayoutFormat == null)
+				_emptyTextLayoutFormat = new TextLayoutFormatValueHolder();
+			return _emptyTextLayoutFormat;
+		}
+
+
+		private var _color:*;
+		private var _backgroundColor:*;
+		private var _lineThrough:*;
+		private var _textAlpha:*;
+		private var _backgroundAlpha:*;
+		private var _fontSize:*;
+		private var _baselineShift:*;
+		private var _trackingLeft:*;
+		private var _trackingRight:*;
+		private var _lineHeight:*;
+		private var _breakOpportunity:*;
+		private var _digitCase:*;
+		private var _digitWidth:*;
+		private var _dominantBaseline:*;
+		private var _kerning:*;
+		private var _ligatureLevel:*;
+		private var _alignmentBaseline:*;
+		private var _locale:*;
+		private var _typographicCase:*;
+		private var _fontFamily:*;
+		private var _textDecoration:*;
+		private var _fontWeight:*;
+		private var _fontStyle:*;
+		private var _whiteSpaceCollapse:*;
+		private var _renderingMode:*;
+		private var _cffHinting:*;
+		private var _fontLookup:*;
+		private var _textRotation:*;
+		private var _textIndent:*;
+		private var _paragraphStartIndent:*;
+		private var _paragraphEndIndent:*;
+		private var _paragraphSpaceBefore:*;
+		private var _paragraphSpaceAfter:*;
+		private var _textAlign:*;
+		private var _textAlignLast:*;
+		private var _textJustify:*;
+		private var _justificationRule:*;
+		private var _justificationStyle:*;
+		private var _direction:*;
+		private var _tabStops:*;
+		private var _leadingModel:*;
+		private var _columnGap:*;
+		private var _paddingLeft:*;
+		private var _paddingTop:*;
+		private var _paddingRight:*;
+		private var _paddingBottom:*;
+		private var _columnCount:*;
+		private var _columnWidth:*;
+		private var _firstBaselineOffset:*;
+		private var _verticalAlign:*;
+		private var _blockProgression:*;
+		private var _lineBreak:*;
+
+		/**
+		 * Color of the text. A hexadecimal number that specifies three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get color():*
+		{ return _color; }
+		public function set color(newValue:*):void
+		{ _color = _colorProperty.setHelper(_color,newValue); }
+
+		/**
+		 * Background color of the text (adopts default value if undefined during cascade). Can be either the constant value  <code>BackgroundColor.TRANSPARENT</code>, or a hexadecimal value that specifies the three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green.
+		 * <p>Legal values as a string are flashx.textLayout.formats.BackgroundColor.TRANSPARENT, flashx.textLayout.formats.FormatValue.INHERIT and uints from 0x0 to 0xffffffff.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TRANSPARENT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BackgroundColor
+		 */
+		public function get backgroundColor():*
+		{ return _backgroundColor; }
+		public function set backgroundColor(newValue:*):void
+		{ _backgroundColor = _backgroundColorProperty.setHelper(_backgroundColor,newValue); }
+
+		/**
+		 * If <code>true</code>, applies strikethrough, a line drawn through the middle of the text.
+		 * <p>Legal values are true, false and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of false.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineThrough():*
+		{ return _lineThrough; }
+		public function set lineThrough(newValue:*):void
+		{ _lineThrough = _lineThroughProperty.setHelper(_lineThrough,newValue); }
+
+		/**
+		 * Alpha (transparency) value for the text. A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with <code>textAlpha</code> set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textAlpha():*
+		{ return _textAlpha; }
+		public function set textAlpha(newValue:*):void
+		{ _textAlpha = _textAlphaProperty.setHelper(_textAlpha,newValue); }
+
+		/**
+		 * Alpha (transparency) value for the background (adopts default value if undefined during cascade). A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with alpha set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get backgroundAlpha():*
+		{ return _backgroundAlpha; }
+		public function set backgroundAlpha(newValue:*):void
+		{ _backgroundAlpha = _backgroundAlphaProperty.setHelper(_backgroundAlpha,newValue); }
+
+		/**
+		 * The size of the text in pixels.
+		 * <p>Legal values are numbers from 1 to 720 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 12.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontSize():*
+		{ return _fontSize; }
+		public function set fontSize(newValue:*):void
+		{ _fontSize = _fontSizeProperty.setHelper(_fontSize,newValue); }
+
+		/**
+		 * Amount to shift the baseline from the <code>dominantBaseline</code> value. Units are in pixels, or a percentage of <code>fontSize</code> (in which case, enter a string value, like 140%).  Positive values shift the line up for horizontal text (right for vertical) and negative values shift it down for horizontal (left for vertical). 
+		 * <p>Legal values are flashx.textLayout.formats.BaselineShift.SUPERSCRIPT, flashx.textLayout.formats.BaselineShift.SUBSCRIPT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineShift
+		 */
+		public function get baselineShift():*
+		{ return _baselineShift; }
+		public function set baselineShift(newValue:*):void
+		{ _baselineShift = _baselineShiftProperty.setHelper(_baselineShift,newValue); }
+
+		/**
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the left of each character. If kerning is enabled, the <code>trackingLeft</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingLeft</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingLeft():*
+		{ return _trackingLeft; }
+		public function set trackingLeft(newValue:*):void
+		{ _trackingLeft = _trackingLeftProperty.setHelper(_trackingLeft,newValue); }
+
+		/**
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the right of each character.  If kerning is enabled, the <code>trackingRight</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingRight</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingRight():*
+		{ return _trackingRight; }
+		public function set trackingRight(newValue:*):void
+		{ _trackingRight = _trackingRightProperty.setHelper(_trackingRight,newValue); }
+
+		/**
+		 * Leading controls for the text. The distance from the baseline of the previous or the next line (based on <code>LeadingModel</code>) to the baseline of the current line is equal to the maximum amount of the leading applied to any character in the line. This is either a number or a percent.  If specifying a percent, enter a string value, like 140%.<p><img src='../../../images/textLayout_lineHeight1.jpg' alt='lineHeight1' /><img src='../../../images/textLayout_lineHeight2.jpg' alt='lineHeight2' /></p>
+		 * <p>Legal values as a number are from -720 to 720.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 120%.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineHeight():*
+		{ return _lineHeight; }
+		public function set lineHeight(newValue:*):void
+		{ _lineHeight = _lineHeightProperty.setHelper(_lineHeight,newValue); }
+
+		/**
+		 * Controls where lines are allowed to break when breaking wrapping text into multiple lines. Set to <code>BreakOpportunity.AUTO</code> to break text normally. Set to <code>BreakOpportunity.NONE</code> to <em>not</em> break the text unless the text would overrun the measure and there are no other places to break the line. Set to <code>BreakOpportunity.ANY</code> to allow the line to break anywhere, rather than just between words. Set to <code>BreakOpportunity.ALL</code> to have each typographic cluster put on a separate line (useful for text on a path).
+		 * <p>Legal values are flash.text.engine.BreakOpportunity.ALL, flash.text.engine.BreakOpportunity.ANY, flash.text.engine.BreakOpportunity.AUTO, flash.text.engine.BreakOpportunity.NONE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.BreakOpportunity
+		 */
+		public function get breakOpportunity():*
+		{ return _breakOpportunity; }
+		public function set breakOpportunity(newValue:*):void
+		{ _breakOpportunity = _breakOpportunityProperty.setHelper(_breakOpportunity,newValue); }
+
+		/**
+		 * The type of digit case used for this text. Setting the value to <code>DigitCase.OLD_STYLE</code> approximates lowercase letterforms with varying ascenders and descenders. The figures are proportionally spaced. This style is only available in selected typefaces, most commonly in a supplemental or expert font. The <code>DigitCase.LINING</code> setting has all-cap height and is typically monospaced to line up in charts.<p><img src='../../../images/textLayout_digitcase.gif' alt='digitCase' /></p>
+		 * <p>Legal values are flash.text.engine.DigitCase.DEFAULT, flash.text.engine.DigitCase.LINING, flash.text.engine.DigitCase.OLD_STYLE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitCase
+		 */
+		public function get digitCase():*
+		{ return _digitCase; }
+		public function set digitCase(newValue:*):void
+		{ _digitCase = _digitCaseProperty.setHelper(_digitCase,newValue); }
+
+		/**
+		 * Type of digit width used for this text. This can be <code>DigitWidth.PROPORTIONAL</code>, which looks best for individual numbers, or <code>DigitWidth.TABULAR</code>, which works best for numbers in tables, charts, and vertical rows.<p><img src='../../../images/textLayout_digitwidth.gif' alt='digitWidth' /></p>
+		 * <p>Legal values are flash.text.engine.DigitWidth.DEFAULT, flash.text.engine.DigitWidth.PROPORTIONAL, flash.text.engine.DigitWidth.TABULAR, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitWidth
+		 */
+		public function get digitWidth():*
+		{ return _digitWidth; }
+		public function set digitWidth(newValue:*):void
+		{ _digitWidth = _digitWidthProperty.setHelper(_digitWidth,newValue); }
+
+		/**
+		 * Specifies which element baseline snaps to the <code>alignmentBaseline</code> to determine the vertical position of the element on the line. A value of <code>TextBaseline.AUTO</code> selects the dominant baseline based on the <code>locale</code> property of the parent paragraph.  For Japanese and Chinese, the selected baseline value is <code>TextBaseline.IDEOGRAPHIC_CENTER</code>; for all others it is <code>TextBaseline.ROMAN</code>. These baseline choices are determined by the choice of font and the font size.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO, flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get dominantBaseline():*
+		{ return _dominantBaseline; }
+		public function set dominantBaseline(newValue:*):void
+		{ _dominantBaseline = _dominantBaselineProperty.setHelper(_dominantBaseline,newValue); }
+
+		/**
+		 * Kerning adjusts the pixels between certain character pairs to improve readability. Kerning is supported for all fonts with kerning tables.
+		 * <p>Legal values are flash.text.engine.Kerning.ON, flash.text.engine.Kerning.OFF, flash.text.engine.Kerning.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.Kerning
+		 */
+		public function get kerning():*
+		{ return _kerning; }
+		public function set kerning(newValue:*):void
+		{ _kerning = _kerningProperty.setHelper(_kerning,newValue); }
+
+		/**
+		 * Controls which of the ligatures that are defined in the font may be used in the text. The ligatures that appear for each of these settings is dependent on the font. A ligature occurs where two or more letter-forms are joined as a single glyph. Ligatures usually replace consecutive characters sharing common components, such as the letter pairs 'fi', 'fl', or 'ae'. They are used with both Latin and Non-Latin character sets. The ligatures enabled by the values of the LigatureLevel class - <code>MINIMUM</code>, <code>COMMON</code>, <code>UNCOMMON</code>, and <code>EXOTIC</code> - are additive. Each value enables a new set of ligatures, but also includes those of the previous types.<p><b>Note: </b>When working with Arabic or Syriac fonts, <code>ligatureLevel</code> must be set to MINIMUM or above.</p><p><img src='../../../images/textLayout_ligatures.png' alt='ligatureLevel' /></p>
+		 * <p>Legal values are flash.text.engine.LigatureLevel.MINIMUM, flash.text.engine.LigatureLevel.COMMON, flash.text.engine.LigatureLevel.UNCOMMON, flash.text.engine.LigatureLevel.EXOTIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COMMON.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.LigatureLevel
+		 */
+		public function get ligatureLevel():*
+		{ return _ligatureLevel; }
+		public function set ligatureLevel(newValue:*):void
+		{ _ligatureLevel = _ligatureLevelProperty.setHelper(_ligatureLevel,newValue); }
+
+		/**
+		 * Specifies the baseline to which the dominant baseline aligns. For example, if you set <code>dominantBaseline</code> to ASCENT, setting <code>alignmentBaseline</code> to DESCENT aligns the top of the text with the DESCENT baseline, or below the line.  The largest element in the line generally determines the baselines.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of USE_DOMINANT_BASELINE.</p>
+		 * @includeExample examples\TextLayoutFormat_alignmentBaselineExample.as -noswf
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get alignmentBaseline():*
+		{ return _alignmentBaseline; }
+		public function set alignmentBaseline(newValue:*):void
+		{ _alignmentBaseline = _alignmentBaselineProperty.setHelper(_alignmentBaseline,newValue); }
+
+		/**
+		 * The locale of the text. Controls case transformations and shaping. Standard locale identifiers as described in Unicode Technical Standard #35 are used. For example en, en_US and en-US are all English, ja is Japanese. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of en.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get locale():*
+		{ return _locale; }
+		public function set locale(newValue:*):void
+		{ _locale = _localeProperty.setHelper(_locale,newValue); }
+
+		/**
+		 * The type of typographic case used for this text. Here are some examples:<p><img src='../../../images/textLayout_typographiccase.png' alt='typographicCase' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.TLFTypographicCase.DEFAULT, flashx.textLayout.formats.TLFTypographicCase.CAPS_TO_SMALL_CAPS, flashx.textLayout.formats.TLFTypographicCase.UPPERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TLFTypographicCase
+		 */
+		public function get typographicCase():*
+		{ return _typographicCase; }
+		public function set typographicCase(newValue:*):void
+		{ _typographicCase = _typographicCaseProperty.setHelper(_typographicCase,newValue); }
+
+		/**
+		 *  The name of the font to use, or a comma-separated list of font names. The Flash runtime renders the element with the first available font in the list. For example Arial, Helvetica, _sans causes the player to search for Arial, then Helvetica if Arial is not found, then _sans if neither is found.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of Arial.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontFamily():*
+		{ return _fontFamily; }
+		public function set fontFamily(newValue:*):void
+		{ _fontFamily = _fontFamilyProperty.setHelper(_fontFamily,newValue); }
+
+		/**
+		 * Decoration on text. Use to apply underlining; default is none.
+		 * <p>Legal values are flashx.textLayout.formats.TextDecoration.NONE, flashx.textLayout.formats.TextDecoration.UNDERLINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NONE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextDecoration
+		 */
+		public function get textDecoration():*
+		{ return _textDecoration; }
+		public function set textDecoration(newValue:*):void
+		{ _textDecoration = _textDecorationProperty.setHelper(_textDecoration,newValue); }
+
+		/**
+		 * Weight of text. May be <code>FontWeight.NORMAL</code> for use in plain text, or <code>FontWeight.BOLD</code>. Applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontWeight.NORMAL, flash.text.engine.FontWeight.BOLD, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontWeight
+		 */
+		public function get fontWeight():*
+		{ return _fontWeight; }
+		public function set fontWeight(newValue:*):void
+		{ _fontWeight = _fontWeightProperty.setHelper(_fontWeight,newValue); }
+
+		/**
+		 * Style of text. May be <code>FontPosture.NORMAL</code>, for use in plain text, or <code>FontPosture.ITALIC</code> for italic. This property applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontPosture.NORMAL, flash.text.engine.FontPosture.ITALIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontPosture
+		 */
+		public function get fontStyle():*
+		{ return _fontStyle; }
+		public function set fontStyle(newValue:*):void
+		{ _fontStyle = _fontStyleProperty.setHelper(_fontStyle,newValue); }
+
+		/**
+		 * Collapses or preserves whitespace when importing text into a TextFlow. <code>WhiteSpaceCollapse.PRESERVE</code> retains all whitespace characters. <code>WhiteSpaceCollapse.COLLAPSE</code> removes newlines, tabs, and leading or trailing spaces within a block of imported text. Line break tags (&lt;br/&gt;) and Unicode line separator characters are retained.
+		 * <p>Legal values are flashx.textLayout.formats.WhiteSpaceCollapse.PRESERVE, flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COLLAPSE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.WhiteSpaceCollapse
+		 */
+		public function get whiteSpaceCollapse():*
+		{ return _whiteSpaceCollapse; }
+		public function set whiteSpaceCollapse(newValue:*):void
+		{ _whiteSpaceCollapse = _whiteSpaceCollapseProperty.setHelper(_whiteSpaceCollapse,newValue); }
+
+		/**
+		 * The rendering mode used for this text.  Applies only to embedded fonts (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>).
+		 * <p>Legal values are flash.text.engine.RenderingMode.NORMAL, flash.text.engine.RenderingMode.CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of CFF.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.RenderingMode
+		 */
+		public function get renderingMode():*
+		{ return _renderingMode; }
+		public function set renderingMode(newValue:*):void
+		{ _renderingMode = _renderingModeProperty.setHelper(_renderingMode,newValue); }
+
+		/**
+		 * The type of CFF hinting used for this text. CFF hinting determines whether the Flash runtime forces strong horizontal stems to fit to a sub pixel grid or not. This property applies only if the <code>renderingMode</code> property is set to <code>RenderingMode.CFF</code>, and the font is embedded (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>). At small screen sizes, hinting produces a clear, legible text for human readers.
+		 * <p>Legal values are flash.text.engine.CFFHinting.NONE, flash.text.engine.CFFHinting.HORIZONTAL_STEM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of HORIZONTAL_STEM.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.CFFHinting
+		 */
+		public function get cffHinting():*
+		{ return _cffHinting; }
+		public function set cffHinting(newValue:*):void
+		{ _cffHinting = _cffHintingProperty.setHelper(_cffHinting,newValue); }
+
+		/**
+		 * Font lookup to use. Specifying <code>FontLookup.DEVICE</code> uses the fonts installed on the system that is running the SWF file. Device fonts result in a smaller movie size, but text is not always rendered the same across different systems and platforms. Specifying <code>FontLookup.EMBEDDED_CFF</code> uses font outlines embedded in the published SWF file. Embedded fonts increase the size of the SWF file (sometimes dramatically), but text is consistently displayed in the chosen font.
+		 * <p>Legal values are flash.text.engine.FontLookup.DEVICE, flash.text.engine.FontLookup.EMBEDDED_CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEVICE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontLookup
+		 */
+		public function get fontLookup():*
+		{ return _fontLookup; }
+		public function set fontLookup(newValue:*):void
+		{ _fontLookup = _fontLookupProperty.setHelper(_fontLookup,newValue); }
+
+		/**
+		 * Determines the number of degrees to rotate this text.
+		 * <p>Legal values are flash.text.engine.TextRotation.ROTATE_0, flash.text.engine.TextRotation.ROTATE_180, flash.text.engine.TextRotation.ROTATE_270, flash.text.engine.TextRotation.ROTATE_90, flash.text.engine.TextRotation.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextRotation
+		 */
+		public function get textRotation():*
+		{ return _textRotation; }
+		public function set textRotation(newValue:*):void
+		{ _textRotation = _textRotationProperty.setHelper(_textRotation,newValue); }
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the first line of the paragraph.
+		 * A negative indent will push the line into the margin, and possibly out of the container.
+		 * <p>Legal values are numbers from -1000 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textIndent():*
+		{ return _textIndent; }
+		public function set textIndent(newValue:*):void
+		{ _textIndent = _textIndentProperty.setHelper(_textIndent,newValue); }
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's start edge. Refers to the left edge in left-to-right text and the right edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphStartIndent():*
+		{ return _paragraphStartIndent; }
+		public function set paragraphStartIndent(newValue:*):void
+		{ _paragraphStartIndent = _paragraphStartIndentProperty.setHelper(_paragraphStartIndent,newValue); }
+
+		/**
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's end edge. Refers to the right edge in left-to-right text and the left edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphEndIndent():*
+		{ return _paragraphEndIndent; }
+		public function set paragraphEndIndent(newValue:*):void
+		{ _paragraphEndIndent = _paragraphEndIndentProperty.setHelper(_paragraphEndIndent,newValue); }
+
+		/**
+		 * A Number that specifies the amount of space, in pixels, to leave before the paragraph. 
+		 * Collapses in tandem with <code>paragraphSpaceAfter</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceBefore():*
+		{ return _paragraphSpaceBefore; }
+		public function set paragraphSpaceBefore(newValue:*):void
+		{ _paragraphSpaceBefore = _paragraphSpaceBeforeProperty.setHelper(_paragraphSpaceBefore,newValue); }
+
+		/**
+		 * A Number that specifies the amount of space, in pixels, to leave after the paragraph.
+		 * Collapses in tandem with  <code>paragraphSpaceBefore</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceAfter():*
+		{ return _paragraphSpaceAfter; }
+		public function set paragraphSpaceAfter(newValue:*):void
+		{ _paragraphSpaceAfter = _paragraphSpaceAfterProperty.setHelper(_paragraphSpaceAfter,newValue); }
+
+		/**
+		 * Alignment of lines in the paragraph relative to the container.
+		 * <code>TextAlign.LEFT</code> aligns lines along the left edge of the container. <code>TextAlign.RIGHT</code> aligns on the right edge. <code>TextAlign.CENTER</code> positions the line equidistant from the left and right edges. <code>TextAlign.JUSTIFY</code> spreads the lines out so they fill the space. <code>TextAlign.START</code> is equivalent to setting left in left-to-right text, or right in right-to-left text. <code>TextAlign.END</code> is equivalent to setting right in left-to-right text, or left in right-to-left text.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlign():*
+		{ return _textAlign; }
+		public function set textAlign(newValue:*):void
+		{ _textAlign = _textAlignProperty.setHelper(_textAlign,newValue); }
+
+		/**
+		 * Alignment of the last (or only) line in the paragraph relative to the container in justified text.
+		 * If <code>textAlign</code> is set to <code>TextAlign.JUSTIFY</code>, <code>textAlignLast</code> specifies how the last line (or only line, if this is a one line block) is aligned. Values are similar to <code>textAlign</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlignLast():*
+		{ return _textAlignLast; }
+		public function set textAlignLast(newValue:*):void
+		{ _textAlignLast = _textAlignLastProperty.setHelper(_textAlignLast,newValue); }
+
+		/**
+		 * Specifies options for justifying text.
+		 * Default value is <code>TextJustify.INTER_WORD</code>, meaning that extra space is added to the space characters. <code>TextJustify.DISTRIBUTE</code> adds extra space to space characters and between individual letters. Used only in conjunction with a <code>justificationRule</code> value of <code>JustificationRule.SPACE</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextJustify.INTER_WORD, flashx.textLayout.formats.TextJustify.DISTRIBUTE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of INTER_WORD.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextJustify
+		 */
+		public function get textJustify():*
+		{ return _textJustify; }
+		public function set textJustify(newValue:*):void
+		{ _textJustify = _textJustifyProperty.setHelper(_textJustify,newValue); }
+
+		/**
+		 * Rule used to justify text in a paragraph.
+		 * Default value is <code>FormatValue.AUTO</code>, which justifies text based on the paragraph's <code>locale</code> property. For all languages except Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustificationRule.SPACE</code>, which adds extra space to the space characters.  For Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustficationRule.EAST_ASIAN</code>. In part, justification changes the spacing of punctuation. In Roman text the comma and Japanese periods take a full character's width but in East Asian text only half of a character's width. Also, in the East Asian text the spacing between sequential punctuation marks becomes tighter, obeying traditional East Asian typographic conventions. Note, too, in the example below the leading that is applied to the second line of the paragraphs. In the East Asian version, the last two lines push left. In the Roman version, the second and following lines push left.<p><img src='../../../images/textLayout_justificationrule.png' alt='justificationRule' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.JustificationRule.EAST_ASIAN, flashx.textLayout.formats.JustificationRule.SPACE, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.JustificationRule
+		 */
+		public function get justificationRule():*
+		{ return _justificationRule; }
+		public function set justificationRule(newValue:*):void
+		{ _justificationRule = _justificationRuleProperty.setHelper(_justificationRule,newValue); }
+
+		/**
+		 * The style used for justification of the paragraph. Used only in conjunction with a <code>justificationRule</code> setting of <code>JustificationRule.EAST_ASIAN</code>.
+		 * Default value of <code>FormatValue.AUTO</code> is resolved to <code>JustificationStyle.PUSH_IN_KINSOKU</code> for all locales.  The constants defined by the JustificationStyle class specify options for handling kinsoku characters, which are Japanese characters that cannot appear at either the beginning or end of a line. If you want looser text, specify <code>JustificationStyle.PUSH-OUT-ONLY</code>. If you want behavior that is like what you get with the  <code>justificationRule</code> of <code>JustificationRule.SPACE</code>, use <code>JustificationStyle.PRIORITIZE-LEAST-ADJUSTMENT</code>.
+		 * <p>Legal values are flash.text.engine.JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT, flash.text.engine.JustificationStyle.PUSH_IN_KINSOKU, flash.text.engine.JustificationStyle.PUSH_OUT_ONLY, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.JustificationStyle
+		 */
+		public function get justificationStyle():*
+		{ return _justificationStyle; }
+		public function set justificationStyle(newValue:*):void
+		{ _justificationStyle = _justificationStyleProperty.setHelper(_justificationStyle,newValue); }
+
+		/**
+		 * Specifies the default bidirectional embedding level of the text in the text block. 
+		 * Left-to-right reading order, as in Latin-style scripts, or right-to-left reading order, as in Arabic or Hebrew. This property also affects column direction when it is applied at the container level. Columns can be either left-to-right or right-to-left, just like text. Below are some examples:<p><img src='../../../images/textLayout_direction.gif' alt='direction' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.Direction.LTR, flashx.textLayout.formats.Direction.RTL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of LTR.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.Direction
+		 */
+		public function get direction():*
+		{ return _direction; }
+		public function set direction(newValue:*):void
+		{ _direction = _directionProperty.setHelper(_direction,newValue); }
+
+		/**
+		 * Specifies the tab stops associated with the paragraph.
+		 * Setters can take an array of flashx.textLayout.formats.TabStopFormat, a condensed string representation, undefined, or <code>FormatValue.INHERIT</code>. The condensed string representation is always converted into an array of flashx.textLayout.formats.TabStopFormat. <p>The string-based format is a list of tab stops, where each tab stop is delimited by one or more spaces.</p><p>A tab stop takes the following form: &lt;alignment type&gt;&lt;alignment position&gt;|&lt;alignment token&gt;.</p><p>The alignment type is a single character, and can be S, E, C, or D (or lower-case equivalents). S or s for start, E or e for end, C or c for center, D or d for decimal. The alignment type is optional, and if its not specified will default to S.</p><p>The alignment position is a Number, and is specified according to FXG spec for Numbers (decimal or scientific notation). The alignment position is required.</p><p>The vertical bar is used to separate the alignment position from the alignment token, and should only be present if the alignment token is present.</p><p> The alignment token is optional if the alignment type is D, and should not be present if the alignment type is anything other than D. The alignment token may be any sequence of characters terminated by the space that ends the tab stop (for the last tab stop, the terminating space is optional; end of alignment token is implied). A space may be part of the alignment token if it is escaped with a backslash (\ ). A backslash may be part of the alignment token if it is escaped with another backslash (\\). If the alignment type is D, and the alignment token is not specified, it will take on the default value of null.</p><p>If no tab stops are specified, a tab action defaults to the end of the line.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get tabStops():*
+		{ return _tabStops; }
+		public function set tabStops(newValue:*):void
+		{ _tabStops = _tabStopsProperty.setHelper(_tabStops,newValue); }
+
+		/**
+		 * Specifies the leading model, which is a combination of leading basis and leading direction.
+		 * Leading basis is the baseline to which the <code>lineHeight</code> property refers. Leading direction determines whether the <code>lineHeight</code> property refers to the distance of a line's baseline from that of the line before it or the line after it. The default value of <code>FormatValue.AUTO</code> is resolved based on the paragraph's <code>locale</code> property.  For Japanese and Chinese, it is <code>LeadingModel.IDEOGRAPHIC_TOP_DOWN</code> and for all others it is <code>LeadingModel.ROMAN_UP</code>.<p><strong>Leading Basis:</strong></p><p><img src='../../../images/textLayout_LB1.png' alt='leadingBasis1' />    <img src='../../../images/textLayout_LB2.png' alt='leadingBasis2' />    <img src='../../../images/textLayout_LB3.png' alt='leadingBasis3' /></p><p><strong>Leading Direction:</strong></p><p><img src='../../../images/textLayout_LD1.png' alt='leadingDirection1' />    <img src='../../../images/textLayout_LD2.png' alt='leadingDirection2' />    <img src='../../../images/textLayout_LD3.png' alt='leadingDirection3' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.LeadingModel.ROMAN_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_DOWN, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_DOWN, flashx.textLayout.formats.LeadingModel.APPROXIMATE_TEXT_FIELD, flashx.textLayout.formats.LeadingModel.ASCENT_DESCENT_UP, flashx.textLayout.formats.LeadingModel.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LeadingModel
+		 */
+		public function get leadingModel():*
+		{ return _leadingModel; }
+		public function set leadingModel(newValue:*):void
+		{ _leadingModel = _leadingModelProperty.setHelper(_leadingModel,newValue); }
+
+		/**
+		 * Specifies the amount of gutter space, in pixels, to leave between the columns (adopts default value if undefined during cascade).
+		 * Value is a Number
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 20.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get columnGap():*
+		{ return _columnGap; }
+		public function set columnGap(newValue:*):void
+		{ _columnGap = _columnGapProperty.setHelper(_columnGap,newValue); }
+
+		/**
+		 * Left inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the left edge of the container and the text.  Value is a Number.<p> With vertical text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the end of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingLeft():*
+		{ return _paddingLeft; }
+		public function set paddingLeft(newValue:*):void
+		{ _paddingLeft = _paddingLeftProperty.setHelper(_paddingLeft,newValue); }
+
+		/**
+		 * Top inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the top edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingTop():*
+		{ return _paddingTop; }
+		public function set paddingTop(newValue:*):void
+		{ _paddingTop = _paddingTopProperty.setHelper(_paddingTop,newValue); }
+
+		/**
+		 * Right inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the right edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingRight():*
+		{ return _paddingRight; }
+		public function set paddingRight(newValue:*):void
+		{ _paddingRight = _paddingRightProperty.setHelper(_paddingRight,newValue); }
+
+		/**
+		 * Botttom inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the bottom edge of the container and the text.  Value is a Number. <p> With horizontal text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the bottom of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingBottom():*
+		{ return _paddingBottom; }
+		public function set paddingBottom(newValue:*):void
+		{ _paddingBottom = _paddingBottomProperty.setHelper(_paddingBottom,newValue); }
+
+		/**
+		 * Number of text columns (adopts default value if undefined during cascade).
+		 * The column number overrides the  other column settings. Value is an integer, or <code>FormatValue.AUTO</code> if unspecified. If <code>columnCount</code> is not specified,<code>columnWidth</code> is used to create as many columns as can fit in the container.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and from ints from 1 to 50.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnCount():*
+		{ return _columnCount; }
+		public function set columnCount(newValue:*):void
+		{ _columnCount = _columnCountProperty.setHelper(_columnCount,newValue); }
+
+		/**
+		 * Column width in pixels (adopts default value if undefined during cascade).
+		 * If you specify the width of the columns, but not the count, TextLayout will create as many columns of that width as possible, given the  container width and <code>columnGap</code> settings. Any remainder space is left after the last column. Value is a Number.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 8000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnWidth():*
+		{ return _columnWidth; }
+		public function set columnWidth(newValue:*):void
+		{ _columnWidth = _columnWidthProperty.setHelper(_columnWidth,newValue); }
+
+		/**
+		 * Specifies the baseline position of the first line in the container. Which baseline this property refers to depends on the container-level locale.  For Japanese and Chinese, it is <code>TextBaseline.IDEOGRAPHIC_BOTTOM</code>; for all others it is <code>TextBaseline.ROMAN</code>.
+		 * The offset from the top inset (or right inset if <code>blockProgression</code> is RL) of the container to the baseline of the first line can be either <code>BaselineOffset.ASCENT</code>, meaning equal to the ascent of the line, <code>BaselineOffset.LINE_HEIGHT</code>, meaning equal to the height of that first line, or any fixed-value number to specify an absolute distance. <code>BaselineOffset.AUTO</code> aligns the ascent of the line with the container top inset.<p><img src='../../../images/textLayout_FBO1.png' alt='firstBaselineOffset1' /><img src='../../../images/textLayout_FBO2.png' alt='firstBaselineOffset2' /><img src='../../../images/textLayout_FBO3.png' alt='firstBaselineOffset3' /><img src='../../../images/textLayout_FBO4.png' alt='firstBaselineOffset4' /></p>
+		 * <p>Legal values as a string are flashx.textLayout.formats.BaselineOffset.AUTO, flashx.textLayout.formats.BaselineOffset.ASCENT, flashx.textLayout.formats.BaselineOffset.LINE_HEIGHT, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineOffset
+		 */
+		public function get firstBaselineOffset():*
+		{ return _firstBaselineOffset; }
+		public function set firstBaselineOffset(newValue:*):void
+		{ _firstBaselineOffset = _firstBaselineOffsetProperty.setHelper(_firstBaselineOffset,newValue); }
+
+		/**
+		 * Vertical alignment or justification (adopts default value if undefined during cascade).
+		 * Determines how TextFlow elements align within the container.
+		 * <p>Legal values are flashx.textLayout.formats.VerticalAlign.TOP, flashx.textLayout.formats.VerticalAlign.MIDDLE, flashx.textLayout.formats.VerticalAlign.BOTTOM, flashx.textLayout.formats.VerticalAlign.JUSTIFY, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TOP.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.VerticalAlign
+		 */
+		public function get verticalAlign():*
+		{ return _verticalAlign; }
+		public function set verticalAlign(newValue:*):void
+		{ _verticalAlign = _verticalAlignProperty.setHelper(_verticalAlign,newValue); }
+
+		/**
+		 * Specifies a vertical or horizontal progression of line placement.
+		 * Lines are either placed top-to-bottom (<code>BlockProgression.TB</code>, used for horizontal text) or right-to-left (<code>BlockProgression.RL</code>, used for vertical text).
+		 * <p>Legal values are flashx.textLayout.formats.BlockProgression.RL, flashx.textLayout.formats.BlockProgression.TB, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of TB.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BlockProgression
+		 */
+		public function get blockProgression():*
+		{ return _blockProgression; }
+		public function set blockProgression(newValue:*):void
+		{ _blockProgression = _blockProgressionProperty.setHelper(_blockProgression,newValue); }
+
+		/**
+		 * Controls word wrapping within the container (adopts default value if undefined during cascade).
+		 * Text in the container may be set to fit the width of the container (<code>LineBreak.TO_FIT</code>), or can be set to break only at explicit return or line feed characters (<code>LineBreak.EXPLICIT</code>).
+		 * <p>Legal values are flashx.textLayout.formats.LineBreak.EXPLICIT, flashx.textLayout.formats.LineBreak.TO_FIT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TO_FIT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LineBreak
+		 */
+		public function get lineBreak():*
+		{ return _lineBreak; }
+		public function set lineBreak(newValue:*):void
+		{ _lineBreak = _lineBreakProperty.setHelper(_lineBreak,newValue); }
+
+		/**
+		 * Creates a new TextLayoutFormat object. All settings are empty or, optionally, are initialized from the
+		 * supplied <code>initialValues</code> object.
+		 * 
+		 * @param initialValues optional instance from which to copy initial values.
+		 * 
+		 * @see #defaultFormat
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function TextLayoutFormat(initialValues:ITextLayoutFormat = null)
+		{
+			if (initialValues)
+				apply(initialValues)
+		}
+
+		/**
+		 * Copies TextLayoutFormat settings from the <code>values</code> ITextLayoutFormat instance into this TextLayoutFormat object.
+		 * If <code>values</code> is <code>null</code>, this TextLayoutFormat object is initialized with undefined values for all properties.
+		 * @param values optional instance from which to copy values.
+		 * 
+		 * @includeExample examples\TextLayoutFormat_copyExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function copy(values:ITextLayoutFormat):void
+		{
+			 if (values == null)
+				values = emptyTextLayoutFormat;
+			this.color = values.color;
+			this.backgroundColor = values.backgroundColor;
+			this.lineThrough = values.lineThrough;
+			this.textAlpha = values.textAlpha;
+			this.backgroundAlpha = values.backgroundAlpha;
+			this.fontSize = values.fontSize;
+			this.baselineShift = values.baselineShift;
+			this.trackingLeft = values.trackingLeft;
+			this.trackingRight = values.trackingRight;
+			this.lineHeight = values.lineHeight;
+			this.breakOpportunity = values.breakOpportunity;
+			this.digitCase = values.digitCase;
+			this.digitWidth = values.digitWidth;
+			this.dominantBaseline = values.dominantBaseline;
+			this.kerning = values.kerning;
+			this.ligatureLevel = values.ligatureLevel;
+			this.alignmentBaseline = values.alignmentBaseline;
+			this.locale = values.locale;
+			this.typographicCase = values.typographicCase;
+			this.fontFamily = values.fontFamily;
+			this.textDecoration = values.textDecoration;
+			this.fontWeight = values.fontWeight;
+			this.fontStyle = values.fontStyle;
+			this.whiteSpaceCollapse = values.whiteSpaceCollapse;
+			this.renderingMode = values.renderingMode;
+			this.cffHinting = values.cffHinting;
+			this.fontLookup = values.fontLookup;
+			this.textRotation = values.textRotation;
+			this.textIndent = values.textIndent;
+			this.paragraphStartIndent = values.paragraphStartIndent;
+			this.paragraphEndIndent = values.paragraphEndIndent;
+			this.paragraphSpaceBefore = values.paragraphSpaceBefore;
+			this.paragraphSpaceAfter = values.paragraphSpaceAfter;
+			this.textAlign = values.textAlign;
+			this.textAlignLast = values.textAlignLast;
+			this.textJustify = values.textJustify;
+			this.justificationRule = values.justificationRule;
+			this.justificationStyle = values.justificationStyle;
+			this.direction = values.direction;
+			this.tabStops = values.tabStops;
+			this.leadingModel = values.leadingModel;
+			this.columnGap = values.columnGap;
+			this.paddingLeft = values.paddingLeft;
+			this.paddingTop = values.paddingTop;
+			this.paddingRight = values.paddingRight;
+			this.paddingBottom = values.paddingBottom;
+			this.columnCount = values.columnCount;
+			this.columnWidth = values.columnWidth;
+			this.firstBaselineOffset = values.firstBaselineOffset;
+			this.verticalAlign = values.verticalAlign;
+			this.blockProgression = values.blockProgression;
+			this.lineBreak = values.lineBreak;
+		}
+
+		/**
+		 * Concatenates the values of properties in the <code>incoming</code> ITextLayoutFormat instance
+		 * with the values of this TextLayoutFormat object. In this (the receiving) TextLayoutFormat object, properties whose values are <code>FormatValue.INHERIT</code>,
+		 * and inheriting properties whose values are <code>undefined</code> will get new values from the <code>incoming</code> object.
+		 * Non-inheriting properties whose values are <code>undefined</code> will get their default values.
+		 * All other property values will remain unmodified.
+		 * 
+		 * @param incoming instance from which values are concatenated.
+		 * @see flashx.textLayout.formats.FormatValue#INHERIT
+		 * 
+		 * @includeExample examples\TextLayoutFormat_concatExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function concat(incoming:ITextLayoutFormat):void
+		{
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+					for (var key:String in holder.coreStyles)
+					{
+						this[key] = description[key].concatHelper(this[key],holder.coreStyles[key]);
+				}
+				return;
+			}
+			this.color = _colorProperty.concatHelper(this.color, incoming.color);
+			this.backgroundColor = _backgroundColorProperty.concatHelper(this.backgroundColor, incoming.backgroundColor);
+			this.lineThrough = _lineThroughProperty.concatHelper(this.lineThrough, incoming.lineThrough);
+			this.textAlpha = _textAlphaProperty.concatHelper(this.textAlpha, incoming.textAlpha);
+			this.backgroundAlpha = _backgroundAlphaProperty.concatHelper(this.backgroundAlpha, incoming.backgroundAlpha);
+			this.fontSize = _fontSizeProperty.concatHelper(this.fontSize, incoming.fontSize);
+			this.baselineShift = _baselineShiftProperty.concatHelper(this.baselineShift, incoming.baselineShift);
+			this.trackingLeft = _trackingLeftProperty.concatHelper(this.trackingLeft, incoming.trackingLeft);
+			this.trackingRight = _trackingRightProperty.concatHelper(this.trackingRight, incoming.trackingRight);
+			this.lineHeight = _lineHeightProperty.concatHelper(this.lineHeight, incoming.lineHeight);
+			this.breakOpportunity = _breakOpportunityProperty.concatHelper(this.breakOpportunity, incoming.breakOpportunity);
+			this.digitCase = _digitCaseProperty.concatHelper(this.digitCase, incoming.digitCase);
+			this.digitWidth = _digitWidthProperty.concatHelper(this.digitWidth, incoming.digitWidth);
+			this.dominantBaseline = _dominantBaselineProperty.concatHelper(this.dominantBaseline, incoming.dominantBaseline);
+			this.kerning = _kerningProperty.concatHelper(this.kerning, incoming.kerning);
+			this.ligatureLevel = _ligatureLevelProperty.concatHelper(this.ligatureLevel, incoming.ligatureLevel);
+			this.alignmentBaseline = _alignmentBaselineProperty.concatHelper(this.alignmentBaseline, incoming.alignmentBaseline);
+			this.locale = _localeProperty.concatHelper(this.locale, incoming.locale);
+			this.typographicCase = _typographicCaseProperty.concatHelper(this.typographicCase, incoming.typographicCase);
+			this.fontFamily = _fontFamilyProperty.concatHelper(this.fontFamily, incoming.fontFamily);
+			this.textDecoration = _textDecorationProperty.concatHelper(this.textDecoration, incoming.textDecoration);
+			this.fontWeight = _fontWeightProperty.concatHelper(this.fontWeight, incoming.fontWeight);
+			this.fontStyle = _fontStyleProperty.concatHelper(this.fontStyle, incoming.fontStyle);
+			this.whiteSpaceCollapse = _whiteSpaceCollapseProperty.concatHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse);
+			this.renderingMode = _renderingModeProperty.concatHelper(this.renderingMode, incoming.renderingMode);
+			this.cffHinting = _cffHintingProperty.concatHelper(this.cffHinting, incoming.cffHinting);
+			this.fontLookup = _fontLookupProperty.concatHelper(this.fontLookup, incoming.fontLookup);
+			this.textRotation = _textRotationProperty.concatHelper(this.textRotation, incoming.textRotation);
+			this.textIndent = _textIndentProperty.concatHelper(this.textIndent, incoming.textIndent);
+			this.paragraphStartIndent = _paragraphStartIndentProperty.concatHelper(this.paragraphStartIndent, incoming.paragraphStartIndent);
+			this.paragraphEndIndent = _paragraphEndIndentProperty.concatHelper(this.paragraphEndIndent, incoming.paragraphEndIndent);
+			this.paragraphSpaceBefore = _paragraphSpaceBeforeProperty.concatHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore);
+			this.paragraphSpaceAfter = _paragraphSpaceAfterProperty.concatHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter);
+			this.textAlign = _textAlignProperty.concatHelper(this.textAlign, incoming.textAlign);
+			this.textAlignLast = _textAlignLastProperty.concatHelper(this.textAlignLast, incoming.textAlignLast);
+			this.textJustify = _textJustifyProperty.concatHelper(this.textJustify, incoming.textJustify);
+			this.justificationRule = _justificationRuleProperty.concatHelper(this.justificationRule, incoming.justificationRule);
+			this.justificationStyle = _justificationStyleProperty.concatHelper(this.justificationStyle, incoming.justificationStyle);
+			this.direction = _directionProperty.concatHelper(this.direction, incoming.direction);
+			this.tabStops = _tabStopsProperty.concatHelper(this.tabStops, incoming.tabStops);
+			this.leadingModel = _leadingModelProperty.concatHelper(this.leadingModel, incoming.leadingModel);
+			this.columnGap = _columnGapProperty.concatHelper(this.columnGap, incoming.columnGap);
+			this.paddingLeft = _paddingLeftProperty.concatHelper(this.paddingLeft, incoming.paddingLeft);
+			this.paddingTop = _paddingTopProperty.concatHelper(this.paddingTop, incoming.paddingTop);
+			this.paddingRight = _paddingRightProperty.concatHelper(this.paddingRight, incoming.paddingRight);
+			this.paddingBottom = _paddingBottomProperty.concatHelper(this.paddingBottom, incoming.paddingBottom);
+			this.columnCount = _columnCountProperty.concatHelper(this.columnCount, incoming.columnCount);
+			this.columnWidth = _columnWidthProperty.concatHelper(this.columnWidth, incoming.columnWidth);
+			this.firstBaselineOffset = _firstBaselineOffsetProperty.concatHelper(this.firstBaselineOffset, incoming.firstBaselineOffset);
+			this.verticalAlign = _verticalAlignProperty.concatHelper(this.verticalAlign, incoming.verticalAlign);
+			this.blockProgression = _blockProgressionProperty.concatHelper(this.blockProgression, incoming.blockProgression);
+			this.lineBreak = _lineBreakProperty.concatHelper(this.lineBreak, incoming.lineBreak);
+		}
+
+		/**
+		 * Concatenates the values of properties in the <code>incoming</code> ITextLayoutFormat instance
+		 * with the values of this TextLayoutFormat object. In this (the receiving) TextLayoutFormat object, properties whose values are <code>FormatValue.INHERIT</code>,
+		 * and inheriting properties whose values are <code>undefined</code> will get new values from the <code>incoming</code> object.
+		 * All other property values will remain unmodified.
+		 * 
+		 * @param incoming instance from which values are concatenated.
+		 * @see flashx.textLayout.formats.FormatValue#INHERIT
+		 * 
+		 * @includeExample examples\TextLayoutFormat_concatInheritOnlyExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function concatInheritOnly(incoming:ITextLayoutFormat):void
+		{
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+					for (var key:String in holder.coreStyles)
+					{
+						this[key] = description[key].concatInheritOnlyHelper(this[key],holder.coreStyles[key]);
+				}
+				return;
+			}
+			this.color = _colorProperty.concatInheritOnlyHelper(this.color, incoming.color);
+			this.backgroundColor = _backgroundColorProperty.concatInheritOnlyHelper(this.backgroundColor, incoming.backgroundColor);
+			this.lineThrough = _lineThroughProperty.concatInheritOnlyHelper(this.lineThrough, incoming.lineThrough);
+			this.textAlpha = _textAlphaProperty.concatInheritOnlyHelper(this.textAlpha, incoming.textAlpha);
+			this.backgroundAlpha = _backgroundAlphaProperty.concatInheritOnlyHelper(this.backgroundAlpha, incoming.backgroundAlpha);
+			this.fontSize = _fontSizeProperty.concatInheritOnlyHelper(this.fontSize, incoming.fontSize);
+			this.baselineShift = _baselineShiftProperty.concatInheritOnlyHelper(this.baselineShift, incoming.baselineShift);
+			this.trackingLeft = _trackingLeftProperty.concatInheritOnlyHelper(this.trackingLeft, incoming.trackingLeft);
+			this.trackingRight = _trackingRightProperty.concatInheritOnlyHelper(this.trackingRight, incoming.trackingRight);
+			this.lineHeight = _lineHeightProperty.concatInheritOnlyHelper(this.lineHeight, incoming.lineHeight);
+			this.breakOpportunity = _breakOpportunityProperty.concatInheritOnlyHelper(this.breakOpportunity, incoming.breakOpportunity);
+			this.digitCase = _digitCaseProperty.concatInheritOnlyHelper(this.digitCase, incoming.digitCase);
+			this.digitWidth = _digitWidthProperty.concatInheritOnlyHelper(this.digitWidth, incoming.digitWidth);
+			this.dominantBaseline = _dominantBaselineProperty.concatInheritOnlyHelper(this.dominantBaseline, incoming.dominantBaseline);
+			this.kerning = _kerningProperty.concatInheritOnlyHelper(this.kerning, incoming.kerning);
+			this.ligatureLevel = _ligatureLevelProperty.concatInheritOnlyHelper(this.ligatureLevel, incoming.ligatureLevel);
+			this.alignmentBaseline = _alignmentBaselineProperty.concatInheritOnlyHelper(this.alignmentBaseline, incoming.alignmentBaseline);
+			this.locale = _localeProperty.concatInheritOnlyHelper(this.locale, incoming.locale);
+			this.typographicCase = _typographicCaseProperty.concatInheritOnlyHelper(this.typographicCase, incoming.typographicCase);
+			this.fontFamily = _fontFamilyProperty.concatInheritOnlyHelper(this.fontFamily, incoming.fontFamily);
+			this.textDecoration = _textDecorationProperty.concatInheritOnlyHelper(this.textDecoration, incoming.textDecoration);
+			this.fontWeight = _fontWeightProperty.concatInheritOnlyHelper(this.fontWeight, incoming.fontWeight);
+			this.fontStyle = _fontStyleProperty.concatInheritOnlyHelper(this.fontStyle, incoming.fontStyle);
+			this.whiteSpaceCollapse = _whiteSpaceCollapseProperty.concatInheritOnlyHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse);
+			this.renderingMode = _renderingModeProperty.concatInheritOnlyHelper(this.renderingMode, incoming.renderingMode);
+			this.cffHinting = _cffHintingProperty.concatInheritOnlyHelper(this.cffHinting, incoming.cffHinting);
+			this.fontLookup = _fontLookupProperty.concatInheritOnlyHelper(this.fontLookup, incoming.fontLookup);
+			this.textRotation = _textRotationProperty.concatInheritOnlyHelper(this.textRotation, incoming.textRotation);
+			this.textIndent = _textIndentProperty.concatInheritOnlyHelper(this.textIndent, incoming.textIndent);
+			this.paragraphStartIndent = _paragraphStartIndentProperty.concatInheritOnlyHelper(this.paragraphStartIndent, incoming.paragraphStartIndent);
+			this.paragraphEndIndent = _paragraphEndIndentProperty.concatInheritOnlyHelper(this.paragraphEndIndent, incoming.paragraphEndIndent);
+			this.paragraphSpaceBefore = _paragraphSpaceBeforeProperty.concatInheritOnlyHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore);
+			this.paragraphSpaceAfter = _paragraphSpaceAfterProperty.concatInheritOnlyHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter);
+			this.textAlign = _textAlignProperty.concatInheritOnlyHelper(this.textAlign, incoming.textAlign);
+			this.textAlignLast = _textAlignLastProperty.concatInheritOnlyHelper(this.textAlignLast, incoming.textAlignLast);
+			this.textJustify = _textJustifyProperty.concatInheritOnlyHelper(this.textJustify, incoming.textJustify);
+			this.justificationRule = _justificationRuleProperty.concatInheritOnlyHelper(this.justificationRule, incoming.justificationRule);
+			this.justificationStyle = _justificationStyleProperty.concatInheritOnlyHelper(this.justificationStyle, incoming.justificationStyle);
+			this.direction = _directionProperty.concatInheritOnlyHelper(this.direction, incoming.direction);
+			this.tabStops = _tabStopsProperty.concatInheritOnlyHelper(this.tabStops, incoming.tabStops);
+			this.leadingModel = _leadingModelProperty.concatInheritOnlyHelper(this.leadingModel, incoming.leadingModel);
+			this.columnGap = _columnGapProperty.concatInheritOnlyHelper(this.columnGap, incoming.columnGap);
+			this.paddingLeft = _paddingLeftProperty.concatInheritOnlyHelper(this.paddingLeft, incoming.paddingLeft);
+			this.paddingTop = _paddingTopProperty.concatInheritOnlyHelper(this.paddingTop, incoming.paddingTop);
+			this.paddingRight = _paddingRightProperty.concatInheritOnlyHelper(this.paddingRight, incoming.paddingRight);
+			this.paddingBottom = _paddingBottomProperty.concatInheritOnlyHelper(this.paddingBottom, incoming.paddingBottom);
+			this.columnCount = _columnCountProperty.concatInheritOnlyHelper(this.columnCount, incoming.columnCount);
+			this.columnWidth = _columnWidthProperty.concatInheritOnlyHelper(this.columnWidth, incoming.columnWidth);
+			this.firstBaselineOffset = _firstBaselineOffsetProperty.concatInheritOnlyHelper(this.firstBaselineOffset, incoming.firstBaselineOffset);
+			this.verticalAlign = _verticalAlignProperty.concatInheritOnlyHelper(this.verticalAlign, incoming.verticalAlign);
+			this.blockProgression = _blockProgressionProperty.concatInheritOnlyHelper(this.blockProgression, incoming.blockProgression);
+			this.lineBreak = _lineBreakProperty.concatInheritOnlyHelper(this.lineBreak, incoming.lineBreak);
+		}
+
+		/**
+		 * Replaces property values in this TextLayoutFormat object with the values of properties that are set in
+		 * the <code>incoming</code> ITextLayoutFormat instance. Properties that are <code>undefined</code> in the <code>incoming</code>
+		 * ITextLayoutFormat instance are not changed in this object.
+		 * 
+		 * @param incoming instance whose property values are applied to this TextLayoutFormat object.
+		 * 
+		 * @includeExample examples\TextLayoutFormat_applyExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function apply(incoming:ITextLayoutFormat):void
+		{
+			var val:*;
+
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+					for (var key:String in holder.coreStyles)
+					{
+						CONFIG::debug { assert(holder.coreStyles[key] !== undefined,"bad value in apply"); }
+						this[key] = holder.coreStyles[key];
+				}
+				return;
+			}
+
+			if ((val = incoming.color) !== undefined)
+				this.color = val;
+			if ((val = incoming.backgroundColor) !== undefined)
+				this.backgroundColor = val;
+			if ((val = incoming.lineThrough) !== undefined)
+				this.lineThrough = val;
+			if ((val = incoming.textAlpha) !== undefined)
+				this.textAlpha = val;
+			if ((val = incoming.backgroundAlpha) !== undefined)
+				this.backgroundAlpha = val;
+			if ((val = incoming.fontSize) !== undefined)
+				this.fontSize = val;
+			if ((val = incoming.baselineShift) !== undefined)
+				this.baselineShift = val;
+			if ((val = incoming.trackingLeft) !== undefined)
+				this.trackingLeft = val;
+			if ((val = incoming.trackingRight) !== undefined)
+				this.trackingRight = val;
+			if ((val = incoming.lineHeight) !== undefined)
+				this.lineHeight = val;
+			if ((val = incoming.breakOpportunity) !== undefined)
+				this.breakOpportunity = val;
+			if ((val = incoming.digitCase) !== undefined)
+				this.digitCase = val;
+			if ((val = incoming.digitWidth) !== undefined)
+				this.digitWidth = val;
+			if ((val = incoming.dominantBaseline) !== undefined)
+				this.dominantBaseline = val;
+			if ((val = incoming.kerning) !== undefined)
+				this.kerning = val;
+			if ((val = incoming.ligatureLevel) !== undefined)
+				this.ligatureLevel = val;
+			if ((val = incoming.alignmentBaseline) !== undefined)
+				this.alignmentBaseline = val;
+			if ((val = incoming.locale) !== undefined)
+				this.locale = val;
+			if ((val = incoming.typographicCase) !== undefined)
+				this.typographicCase = val;
+			if ((val = incoming.fontFamily) !== undefined)
+				this.fontFamily = val;
+			if ((val = incoming.textDecoration) !== undefined)
+				this.textDecoration = val;
+			if ((val = incoming.fontWeight) !== undefined)
+				this.fontWeight = val;
+			if ((val = incoming.fontStyle) !== undefined)
+				this.fontStyle = val;
+			if ((val = incoming.whiteSpaceCollapse) !== undefined)
+				this.whiteSpaceCollapse = val;
+			if ((val = incoming.renderingMode) !== undefined)
+				this.renderingMode = val;
+			if ((val = incoming.cffHinting) !== undefined)
+				this.cffHinting = val;
+			if ((val = incoming.fontLookup) !== undefined)
+				this.fontLookup = val;
+			if ((val = incoming.textRotation) !== undefined)
+				this.textRotation = val;
+			if ((val = incoming.textIndent) !== undefined)
+				this.textIndent = val;
+			if ((val = incoming.paragraphStartIndent) !== undefined)
+				this.paragraphStartIndent = val;
+			if ((val = incoming.paragraphEndIndent) !== undefined)
+				this.paragraphEndIndent = val;
+			if ((val = incoming.paragraphSpaceBefore) !== undefined)
+				this.paragraphSpaceBefore = val;
+			if ((val = incoming.paragraphSpaceAfter) !== undefined)
+				this.paragraphSpaceAfter = val;
+			if ((val = incoming.textAlign) !== undefined)
+				this.textAlign = val;
+			if ((val = incoming.textAlignLast) !== undefined)
+				this.textAlignLast = val;
+			if ((val = incoming.textJustify) !== undefined)
+				this.textJustify = val;
+			if ((val = incoming.justificationRule) !== undefined)
+				this.justificationRule = val;
+			if ((val = incoming.justificationStyle) !== undefined)
+				this.justificationStyle = val;
+			if ((val = incoming.direction) !== undefined)
+				this.direction = val;
+			if ((val = incoming.tabStops) !== undefined)
+				this.tabStops = val;
+			if ((val = incoming.leadingModel) !== undefined)
+				this.leadingModel = val;
+			if ((val = incoming.columnGap) !== undefined)
+				this.columnGap = val;
+			if ((val = incoming.paddingLeft) !== undefined)
+				this.paddingLeft = val;
+			if ((val = incoming.paddingTop) !== undefined)
+				this.paddingTop = val;
+			if ((val = incoming.paddingRight) !== undefined)
+				this.paddingRight = val;
+			if ((val = incoming.paddingBottom) !== undefined)
+				this.paddingBottom = val;
+			if ((val = incoming.columnCount) !== undefined)
+				this.columnCount = val;
+			if ((val = incoming.columnWidth) !== undefined)
+				this.columnWidth = val;
+			if ((val = incoming.firstBaselineOffset) !== undefined)
+				this.firstBaselineOffset = val;
+			if ((val = incoming.verticalAlign) !== undefined)
+				this.verticalAlign = val;
+			if ((val = incoming.blockProgression) !== undefined)
+				this.blockProgression = val;
+			if ((val = incoming.lineBreak) !== undefined)
+				this.lineBreak = val;
+		}
+
+		/**
+		 * Compares properties in ITextLayoutFormat instance <code>p1</code> with properties in ITextLayoutFormat instance <code>p2</code>
+		 * and returns <code>true</code> if all properties match.
+		 * 
+		 * @param p1 instance to compare to <code>p2</code>.
+		 * @param p2 instance to compare to <code>p1</code>.
+		 * 
+		 * @return true if all properties match, false otherwise.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isEqual(p1:ITextLayoutFormat,p2:ITextLayoutFormat):Boolean
+		{
+			if (p1 == null)
+				p1 = emptyTextLayoutFormat;
+			if (p2 == null)
+				p2 = emptyTextLayoutFormat;
+			if (p1 == p2)
+				return true;
+			var p1Holder:TextLayoutFormatValueHolder = p1 as TextLayoutFormatValueHolder;
+			var p2Holder:TextLayoutFormatValueHolder = p2 as TextLayoutFormatValueHolder;
+			if (p1Holder && p2Holder)
+				return Property.equalCoreStyles(p1Holder.coreStyles,p2Holder.coreStyles,TextLayoutFormat.description);
+
+			if (!_colorProperty.equalHelper(p1.color, p2.color))
+				return false;
+			if (!_backgroundColorProperty.equalHelper(p1.backgroundColor, p2.backgroundColor))
+				return false;
+			if (!_lineThroughProperty.equalHelper(p1.lineThrough, p2.lineThrough))
+				return false;
+			if (!_textAlphaProperty.equalHelper(p1.textAlpha, p2.textAlpha))
+				return false;
+			if (!_backgroundAlphaProperty.equalHelper(p1.backgroundAlpha, p2.backgroundAlpha))
+				return false;
+			if (!_fontSizeProperty.equalHelper(p1.fontSize, p2.fontSize))
+				return false;
+			if (!_baselineShiftProperty.equalHelper(p1.baselineShift, p2.baselineShift))
+				return false;
+			if (!_trackingLeftProperty.equalHelper(p1.trackingLeft, p2.trackingLeft))
+				return false;
+			if (!_trackingRightProperty.equalHelper(p1.trackingRight, p2.trackingRight))
+				return false;
+			if (!_lineHeightProperty.equalHelper(p1.lineHeight, p2.lineHeight))
+				return false;
+			if (!_breakOpportunityProperty.equalHelper(p1.breakOpportunity, p2.breakOpportunity))
+				return false;
+			if (!_digitCaseProperty.equalHelper(p1.digitCase, p2.digitCase))
+				return false;
+			if (!_digitWidthProperty.equalHelper(p1.digitWidth, p2.digitWidth))
+				return false;
+			if (!_dominantBaselineProperty.equalHelper(p1.dominantBaseline, p2.dominantBaseline))
+				return false;
+			if (!_kerningProperty.equalHelper(p1.kerning, p2.kerning))
+				return false;
+			if (!_ligatureLevelProperty.equalHelper(p1.ligatureLevel, p2.ligatureLevel))
+				return false;
+			if (!_alignmentBaselineProperty.equalHelper(p1.alignmentBaseline, p2.alignmentBaseline))
+				return false;
+			if (!_localeProperty.equalHelper(p1.locale, p2.locale))
+				return false;
+			if (!_typographicCaseProperty.equalHelper(p1.typographicCase, p2.typographicCase))
+				return false;
+			if (!_fontFamilyProperty.equalHelper(p1.fontFamily, p2.fontFamily))
+				return false;
+			if (!_textDecorationProperty.equalHelper(p1.textDecoration, p2.textDecoration))
+				return false;
+			if (!_fontWeightProperty.equalHelper(p1.fontWeight, p2.fontWeight))
+				return false;
+			if (!_fontStyleProperty.equalHelper(p1.fontStyle, p2.fontStyle))
+				return false;
+			if (!_whiteSpaceCollapseProperty.equalHelper(p1.whiteSpaceCollapse, p2.whiteSpaceCollapse))
+				return false;
+			if (!_renderingModeProperty.equalHelper(p1.renderingMode, p2.renderingMode))
+				return false;
+			if (!_cffHintingProperty.equalHelper(p1.cffHinting, p2.cffHinting))
+				return false;
+			if (!_fontLookupProperty.equalHelper(p1.fontLookup, p2.fontLookup))
+				return false;
+			if (!_textRotationProperty.equalHelper(p1.textRotation, p2.textRotation))
+				return false;
+			if (!_textIndentProperty.equalHelper(p1.textIndent, p2.textIndent))
+				return false;
+			if (!_paragraphStartIndentProperty.equalHelper(p1.paragraphStartIndent, p2.paragraphStartIndent))
+				return false;
+			if (!_paragraphEndIndentProperty.equalHelper(p1.paragraphEndIndent, p2.paragraphEndIndent))
+				return false;
+			if (!_paragraphSpaceBeforeProperty.equalHelper(p1.paragraphSpaceBefore, p2.paragraphSpaceBefore))
+				return false;
+			if (!_paragraphSpaceAfterProperty.equalHelper(p1.paragraphSpaceAfter, p2.paragraphSpaceAfter))
+				return false;
+			if (!_textAlignProperty.equalHelper(p1.textAlign, p2.textAlign))
+				return false;
+			if (!_textAlignLastProperty.equalHelper(p1.textAlignLast, p2.textAlignLast))
+				return false;
+			if (!_textJustifyProperty.equalHelper(p1.textJustify, p2.textJustify))
+				return false;
+			if (!_justificationRuleProperty.equalHelper(p1.justificationRule, p2.justificationRule))
+				return false;
+			if (!_justificationStyleProperty.equalHelper(p1.justificationStyle, p2.justificationStyle))
+				return false;
+			if (!_directionProperty.equalHelper(p1.direction, p2.direction))
+				return false;
+			if (!_tabStopsProperty.equalHelper(p1.tabStops, p2.tabStops))
+				return false;
+			if (!_leadingModelProperty.equalHelper(p1.leadingModel, p2.leadingModel))
+				return false;
+			if (!_columnGapProperty.equalHelper(p1.columnGap, p2.columnGap))
+				return false;
+			if (!_paddingLeftProperty.equalHelper(p1.paddingLeft, p2.paddingLeft))
+				return false;
+			if (!_paddingTopProperty.equalHelper(p1.paddingTop, p2.paddingTop))
+				return false;
+			if (!_paddingRightProperty.equalHelper(p1.paddingRight, p2.paddingRight))
+				return false;
+			if (!_paddingBottomProperty.equalHelper(p1.paddingBottom, p2.paddingBottom))
+				return false;
+			if (!_columnCountProperty.equalHelper(p1.columnCount, p2.columnCount))
+				return false;
+			if (!_columnWidthProperty.equalHelper(p1.columnWidth, p2.columnWidth))
+				return false;
+			if (!_firstBaselineOffsetProperty.equalHelper(p1.firstBaselineOffset, p2.firstBaselineOffset))
+				return false;
+			if (!_verticalAlignProperty.equalHelper(p1.verticalAlign, p2.verticalAlign))
+				return false;
+			if (!_blockProgressionProperty.equalHelper(p1.blockProgression, p2.blockProgression))
+				return false;
+			if (!_lineBreakProperty.equalHelper(p1.lineBreak, p2.lineBreak))
+				return false;
+
+			return true;
+		}
+
+		/**
+		 * Sets properties in this TextLayoutFormat object to <code>undefined</code> if they match those in the <code>incoming</code>
+		 * ITextLayoutFormat instance.
+		 * 
+		 * @param incoming instance against which to compare this TextLayoutFormat object's property values.
+		 * 
+		 * @includeExample examples\TextLayoutFormat_removeMatchingExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function removeMatching(incoming:ITextLayoutFormat):void
+		{
+			if (incoming == null)
+				return;
+
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+					for (var key:String in holder.coreStyles)
+					{
+						CONFIG::debug { assert(holder.coreStyles[key] !== undefined,"bad value in removeMatching"); }
+						if (description[key].equalHelper(this[key],holder.coreStyles[key]))
+							this[key] = undefined;
+				}
+				return;
+			}
+
+			if (_colorProperty.equalHelper(this.color, incoming.color))
+				this.color = undefined;
+			if (_backgroundColorProperty.equalHelper(this.backgroundColor, incoming.backgroundColor))
+				this.backgroundColor = undefined;
+			if (_lineThroughProperty.equalHelper(this.lineThrough, incoming.lineThrough))
+				this.lineThrough = undefined;
+			if (_textAlphaProperty.equalHelper(this.textAlpha, incoming.textAlpha))
+				this.textAlpha = undefined;
+			if (_backgroundAlphaProperty.equalHelper(this.backgroundAlpha, incoming.backgroundAlpha))
+				this.backgroundAlpha = undefined;
+			if (_fontSizeProperty.equalHelper(this.fontSize, incoming.fontSize))
+				this.fontSize = undefined;
+			if (_baselineShiftProperty.equalHelper(this.baselineShift, incoming.baselineShift))
+				this.baselineShift = undefined;
+			if (_trackingLeftProperty.equalHelper(this.trackingLeft, incoming.trackingLeft))
+				this.trackingLeft = undefined;
+			if (_trackingRightProperty.equalHelper(this.trackingRight, incoming.trackingRight))
+				this.trackingRight = undefined;
+			if (_lineHeightProperty.equalHelper(this.lineHeight, incoming.lineHeight))
+				this.lineHeight = undefined;
+			if (_breakOpportunityProperty.equalHelper(this.breakOpportunity, incoming.breakOpportunity))
+				this.breakOpportunity = undefined;
+			if (_digitCaseProperty.equalHelper(this.digitCase, incoming.digitCase))
+				this.digitCase = undefined;
+			if (_digitWidthProperty.equalHelper(this.digitWidth, incoming.digitWidth))
+				this.digitWidth = undefined;
+			if (_dominantBaselineProperty.equalHelper(this.dominantBaseline, incoming.dominantBaseline))
+				this.dominantBaseline = undefined;
+			if (_kerningProperty.equalHelper(this.kerning, incoming.kerning))
+				this.kerning = undefined;
+			if (_ligatureLevelProperty.equalHelper(this.ligatureLevel, incoming.ligatureLevel))
+				this.ligatureLevel = undefined;
+			if (_alignmentBaselineProperty.equalHelper(this.alignmentBaseline, incoming.alignmentBaseline))
+				this.alignmentBaseline = undefined;
+			if (_localeProperty.equalHelper(this.locale, incoming.locale))
+				this.locale = undefined;
+			if (_typographicCaseProperty.equalHelper(this.typographicCase, incoming.typographicCase))
+				this.typographicCase = undefined;
+			if (_fontFamilyProperty.equalHelper(this.fontFamily, incoming.fontFamily))
+				this.fontFamily = undefined;
+			if (_textDecorationProperty.equalHelper(this.textDecoration, incoming.textDecoration))
+				this.textDecoration = undefined;
+			if (_fontWeightProperty.equalHelper(this.fontWeight, incoming.fontWeight))
+				this.fontWeight = undefined;
+			if (_fontStyleProperty.equalHelper(this.fontStyle, incoming.fontStyle))
+				this.fontStyle = undefined;
+			if (_whiteSpaceCollapseProperty.equalHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse))
+				this.whiteSpaceCollapse = undefined;
+			if (_renderingModeProperty.equalHelper(this.renderingMode, incoming.renderingMode))
+				this.renderingMode = undefined;
+			if (_cffHintingProperty.equalHelper(this.cffHinting, incoming.cffHinting))
+				this.cffHinting = undefined;
+			if (_fontLookupProperty.equalHelper(this.fontLookup, incoming.fontLookup))
+				this.fontLookup = undefined;
+			if (_textRotationProperty.equalHelper(this.textRotation, incoming.textRotation))
+				this.textRotation = undefined;
+			if (_textIndentProperty.equalHelper(this.textIndent, incoming.textIndent))
+				this.textIndent = undefined;
+			if (_paragraphStartIndentProperty.equalHelper(this.paragraphStartIndent, incoming.paragraphStartIndent))
+				this.paragraphStartIndent = undefined;
+			if (_paragraphEndIndentProperty.equalHelper(this.paragraphEndIndent, incoming.paragraphEndIndent))
+				this.paragraphEndIndent = undefined;
+			if (_paragraphSpaceBeforeProperty.equalHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore))
+				this.paragraphSpaceBefore = undefined;
+			if (_paragraphSpaceAfterProperty.equalHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter))
+				this.paragraphSpaceAfter = undefined;
+			if (_textAlignProperty.equalHelper(this.textAlign, incoming.textAlign))
+				this.textAlign = undefined;
+			if (_textAlignLastProperty.equalHelper(this.textAlignLast, incoming.textAlignLast))
+				this.textAlignLast = undefined;
+			if (_textJustifyProperty.equalHelper(this.textJustify, incoming.textJustify))
+				this.textJustify = undefined;
+			if (_justificationRuleProperty.equalHelper(this.justificationRule, incoming.justificationRule))
+				this.justificationRule = undefined;
+			if (_justificationStyleProperty.equalHelper(this.justificationStyle, incoming.justificationStyle))
+				this.justificationStyle = undefined;
+			if (_directionProperty.equalHelper(this.direction, incoming.direction))
+				this.direction = undefined;
+			if (_tabStopsProperty.equalHelper(this.tabStops, incoming.tabStops))
+				this.tabStops = undefined;
+			if (_leadingModelProperty.equalHelper(this.leadingModel, incoming.leadingModel))
+				this.leadingModel = undefined;
+			if (_columnGapProperty.equalHelper(this.columnGap, incoming.columnGap))
+				this.columnGap = undefined;
+			if (_paddingLeftProperty.equalHelper(this.paddingLeft, incoming.paddingLeft))
+				this.paddingLeft = undefined;
+			if (_paddingTopProperty.equalHelper(this.paddingTop, incoming.paddingTop))
+				this.paddingTop = undefined;
+			if (_paddingRightProperty.equalHelper(this.paddingRight, incoming.paddingRight))
+				this.paddingRight = undefined;
+			if (_paddingBottomProperty.equalHelper(this.paddingBottom, incoming.paddingBottom))
+				this.paddingBottom = undefined;
+			if (_columnCountProperty.equalHelper(this.columnCount, incoming.columnCount))
+				this.columnCount = undefined;
+			if (_columnWidthProperty.equalHelper(this.columnWidth, incoming.columnWidth))
+				this.columnWidth = undefined;
+			if (_firstBaselineOffsetProperty.equalHelper(this.firstBaselineOffset, incoming.firstBaselineOffset))
+				this.firstBaselineOffset = undefined;
+			if (_verticalAlignProperty.equalHelper(this.verticalAlign, incoming.verticalAlign))
+				this.verticalAlign = undefined;
+			if (_blockProgressionProperty.equalHelper(this.blockProgression, incoming.blockProgression))
+				this.blockProgression = undefined;
+			if (_lineBreakProperty.equalHelper(this.lineBreak, incoming.lineBreak))
+				this.lineBreak = undefined;
+		}
+
+		/**
+		 * Sets properties in this TextLayoutFormat object to <code>undefined</code> if they do not match those in the
+		 * <code>incoming</code> ITextLayoutFormat instance.
+		 * 
+		 * @param incoming instance against which to compare this TextLayoutFormat object's property values.
+		 * 
+		 * @includeExample examples\TextLayoutFormat_removeClashingExample.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function removeClashing(incoming:ITextLayoutFormat):void
+		{
+			if (incoming == null)
+				return;
+
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+					for (var key:String in holder.coreStyles)
+					{
+						CONFIG::debug { assert(holder.coreStyles[key] !== undefined,"bad value in removeClashing"); }
+						if (!description[key].equalHelper(this[key],holder.coreStyles[key]))
+							this[key] = undefined;
+				}
+				return;
+			}
+
+			if (!_colorProperty.equalHelper(this.color, incoming.color))
+				this.color = undefined;
+			if (!_backgroundColorProperty.equalHelper(this.backgroundColor, incoming.backgroundColor))
+				this.backgroundColor = undefined;
+			if (!_lineThroughProperty.equalHelper(this.lineThrough, incoming.lineThrough))
+				this.lineThrough = undefined;
+			if (!_textAlphaProperty.equalHelper(this.textAlpha, incoming.textAlpha))
+				this.textAlpha = undefined;
+			if (!_backgroundAlphaProperty.equalHelper(this.backgroundAlpha, incoming.backgroundAlpha))
+				this.backgroundAlpha = undefined;
+			if (!_fontSizeProperty.equalHelper(this.fontSize, incoming.fontSize))
+				this.fontSize = undefined;
+			if (!_baselineShiftProperty.equalHelper(this.baselineShift, incoming.baselineShift))
+				this.baselineShift = undefined;
+			if (!_trackingLeftProperty.equalHelper(this.trackingLeft, incoming.trackingLeft))
+				this.trackingLeft = undefined;
+			if (!_trackingRightProperty.equalHelper(this.trackingRight, incoming.trackingRight))
+				this.trackingRight = undefined;
+			if (!_lineHeightProperty.equalHelper(this.lineHeight, incoming.lineHeight))
+				this.lineHeight = undefined;
+			if (!_breakOpportunityProperty.equalHelper(this.breakOpportunity, incoming.breakOpportunity))
+				this.breakOpportunity = undefined;
+			if (!_digitCaseProperty.equalHelper(this.digitCase, incoming.digitCase))
+				this.digitCase = undefined;
+			if (!_digitWidthProperty.equalHelper(this.digitWidth, incoming.digitWidth))
+				this.digitWidth = undefined;
+			if (!_dominantBaselineProperty.equalHelper(this.dominantBaseline, incoming.dominantBaseline))
+				this.dominantBaseline = undefined;
+			if (!_kerningProperty.equalHelper(this.kerning, incoming.kerning))
+				this.kerning = undefined;
+			if (!_ligatureLevelProperty.equalHelper(this.ligatureLevel, incoming.ligatureLevel))
+				this.ligatureLevel = undefined;
+			if (!_alignmentBaselineProperty.equalHelper(this.alignmentBaseline, incoming.alignmentBaseline))
+				this.alignmentBaseline = undefined;
+			if (!_localeProperty.equalHelper(this.locale, incoming.locale))
+				this.locale = undefined;
+			if (!_typographicCaseProperty.equalHelper(this.typographicCase, incoming.typographicCase))
+				this.typographicCase = undefined;
+			if (!_fontFamilyProperty.equalHelper(this.fontFamily, incoming.fontFamily))
+				this.fontFamily = undefined;
+			if (!_textDecorationProperty.equalHelper(this.textDecoration, incoming.textDecoration))
+				this.textDecoration = undefined;
+			if (!_fontWeightProperty.equalHelper(this.fontWeight, incoming.fontWeight))
+				this.fontWeight = undefined;
+			if (!_fontStyleProperty.equalHelper(this.fontStyle, incoming.fontStyle))
+				this.fontStyle = undefined;
+			if (!_whiteSpaceCollapseProperty.equalHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse))
+				this.whiteSpaceCollapse = undefined;
+			if (!_renderingModeProperty.equalHelper(this.renderingMode, incoming.renderingMode))
+				this.renderingMode = undefined;
+			if (!_cffHintingProperty.equalHelper(this.cffHinting, incoming.cffHinting))
+				this.cffHinting = undefined;
+			if (!_fontLookupProperty.equalHelper(this.fontLookup, incoming.fontLookup))
+				this.fontLookup = undefined;
+			if (!_textRotationProperty.equalHelper(this.textRotation, incoming.textRotation))
+				this.textRotation = undefined;
+			if (!_textIndentProperty.equalHelper(this.textIndent, incoming.textIndent))
+				this.textIndent = undefined;
+			if (!_paragraphStartIndentProperty.equalHelper(this.paragraphStartIndent, incoming.paragraphStartIndent))
+				this.paragraphStartIndent = undefined;
+			if (!_paragraphEndIndentProperty.equalHelper(this.paragraphEndIndent, incoming.paragraphEndIndent))
+				this.paragraphEndIndent = undefined;
+			if (!_paragraphSpaceBeforeProperty.equalHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore))
+				this.paragraphSpaceBefore = undefined;
+			if (!_paragraphSpaceAfterProperty.equalHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter))
+				this.paragraphSpaceAfter = undefined;
+			if (!_textAlignProperty.equalHelper(this.textAlign, incoming.textAlign))
+				this.textAlign = undefined;
+			if (!_textAlignLastProperty.equalHelper(this.textAlignLast, incoming.textAlignLast))
+				this.textAlignLast = undefined;
+			if (!_textJustifyProperty.equalHelper(this.textJustify, incoming.textJustify))
+				this.textJustify = undefined;
+			if (!_justificationRuleProperty.equalHelper(this.justificationRule, incoming.justificationRule))
+				this.justificationRule = undefined;
+			if (!_justificationStyleProperty.equalHelper(this.justificationStyle, incoming.justificationStyle))
+				this.justificationStyle = undefined;
+			if (!_directionProperty.equalHelper(this.direction, incoming.direction))
+				this.direction = undefined;
+			if (!_tabStopsProperty.equalHelper(this.tabStops, incoming.tabStops))
+				this.tabStops = undefined;
+			if (!_leadingModelProperty.equalHelper(this.leadingModel, incoming.leadingModel))
+				this.leadingModel = undefined;
+			if (!_columnGapProperty.equalHelper(this.columnGap, incoming.columnGap))
+				this.columnGap = undefined;
+			if (!_paddingLeftProperty.equalHelper(this.paddingLeft, incoming.paddingLeft))
+				this.paddingLeft = undefined;
+			if (!_paddingTopProperty.equalHelper(this.paddingTop, incoming.paddingTop))
+				this.paddingTop = undefined;
+			if (!_paddingRightProperty.equalHelper(this.paddingRight, incoming.paddingRight))
+				this.paddingRight = undefined;
+			if (!_paddingBottomProperty.equalHelper(this.paddingBottom, incoming.paddingBottom))
+				this.paddingBottom = undefined;
+			if (!_columnCountProperty.equalHelper(this.columnCount, incoming.columnCount))
+				this.columnCount = undefined;
+			if (!_columnWidthProperty.equalHelper(this.columnWidth, incoming.columnWidth))
+				this.columnWidth = undefined;
+			if (!_firstBaselineOffsetProperty.equalHelper(this.firstBaselineOffset, incoming.firstBaselineOffset))
+				this.firstBaselineOffset = undefined;
+			if (!_verticalAlignProperty.equalHelper(this.verticalAlign, incoming.verticalAlign))
+				this.verticalAlign = undefined;
+			if (!_blockProgressionProperty.equalHelper(this.blockProgression, incoming.blockProgression))
+				this.blockProgression = undefined;
+			if (!_lineBreakProperty.equalHelper(this.lineBreak, incoming.lineBreak))
+				this.lineBreak = undefined;
+		}
+
+		/**
+		 * Gets the TextLayoutFormat hash
+		 * @param seed seed value for the hash algorithm
+		 * @return the TextLayoutFormat hash
+		 * @private
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		tlf_internal function hash(seed:uint):uint
+		{
+			var hash:uint = seed;
+
+			if (_color)
+				hash = _colorProperty.hash(_color, hash);
+			if (_backgroundColor)
+				hash = _backgroundColorProperty.hash(_backgroundColor, hash);
+			if (_lineThrough)
+				hash = _lineThroughProperty.hash(_lineThrough, hash);
+			if (_textAlpha)
+				hash = _textAlphaProperty.hash(_textAlpha, hash);
+			if (_backgroundAlpha)
+				hash = _backgroundAlphaProperty.hash(_backgroundAlpha, hash);
+			if (_fontSize)
+				hash = _fontSizeProperty.hash(_fontSize, hash);
+			if (_baselineShift)
+				hash = _baselineShiftProperty.hash(_baselineShift, hash);
+			if (_trackingLeft)
+				hash = _trackingLeftProperty.hash(_trackingLeft, hash);
+			if (_trackingRight)
+				hash = _trackingRightProperty.hash(_trackingRight, hash);
+			if (_lineHeight)
+				hash = _lineHeightProperty.hash(_lineHeight, hash);
+			if (_breakOpportunity)
+				hash = _breakOpportunityProperty.hash(_breakOpportunity, hash);
+			if (_digitCase)
+				hash = _digitCaseProperty.hash(_digitCase, hash);
+			if (_digitWidth)
+				hash = _digitWidthProperty.hash(_digitWidth, hash);
+			if (_dominantBaseline)
+				hash = _dominantBaselineProperty.hash(_dominantBaseline, hash);
+			if (_kerning)
+				hash = _kerningProperty.hash(_kerning, hash);
+			if (_ligatureLevel)
+				hash = _ligatureLevelProperty.hash(_ligatureLevel, hash);
+			if (_alignmentBaseline)
+				hash = _alignmentBaselineProperty.hash(_alignmentBaseline, hash);
+			if (_locale)
+				hash = _localeProperty.hash(_locale, hash);
+			if (_typographicCase)
+				hash = _typographicCaseProperty.hash(_typographicCase, hash);
+			if (_fontFamily)
+				hash = _fontFamilyProperty.hash(_fontFamily, hash);
+			if (_textDecoration)
+				hash = _textDecorationProperty.hash(_textDecoration, hash);
+			if (_fontWeight)
+				hash = _fontWeightProperty.hash(_fontWeight, hash);
+			if (_fontStyle)
+				hash = _fontStyleProperty.hash(_fontStyle, hash);
+			if (_whiteSpaceCollapse)
+				hash = _whiteSpaceCollapseProperty.hash(_whiteSpaceCollapse, hash);
+			if (_renderingMode)
+				hash = _renderingModeProperty.hash(_renderingMode, hash);
+			if (_cffHinting)
+				hash = _cffHintingProperty.hash(_cffHinting, hash);
+			if (_fontLookup)
+				hash = _fontLookupProperty.hash(_fontLookup, hash);
+			if (_textRotation)
+				hash = _textRotationProperty.hash(_textRotation, hash);
+			if (_textIndent)
+				hash = _textIndentProperty.hash(_textIndent, hash);
+			if (_paragraphStartIndent)
+				hash = _paragraphStartIndentProperty.hash(_paragraphStartIndent, hash);
+			if (_paragraphEndIndent)
+				hash = _paragraphEndIndentProperty.hash(_paragraphEndIndent, hash);
+			if (_paragraphSpaceBefore)
+				hash = _paragraphSpaceBeforeProperty.hash(_paragraphSpaceBefore, hash);
+			if (_paragraphSpaceAfter)
+				hash = _paragraphSpaceAfterProperty.hash(_paragraphSpaceAfter, hash);
+			if (_textAlign)
+				hash = _textAlignProperty.hash(_textAlign, hash);
+			if (_textAlignLast)
+				hash = _textAlignLastProperty.hash(_textAlignLast, hash);
+			if (_textJustify)
+				hash = _textJustifyProperty.hash(_textJustify, hash);
+			if (_justificationRule)
+				hash = _justificationRuleProperty.hash(_justificationRule, hash);
+			if (_justificationStyle)
+				hash = _justificationStyleProperty.hash(_justificationStyle, hash);
+			if (_direction)
+				hash = _directionProperty.hash(_direction, hash);
+			if (_tabStops)
+				hash = _tabStopsProperty.hash(_tabStops, hash);
+			if (_leadingModel)
+				hash = _leadingModelProperty.hash(_leadingModel, hash);
+			if (_columnGap)
+				hash = _columnGapProperty.hash(_columnGap, hash);
+			if (_paddingLeft)
+				hash = _paddingLeftProperty.hash(_paddingLeft, hash);
+			if (_paddingTop)
+				hash = _paddingTopProperty.hash(_paddingTop, hash);
+			if (_paddingRight)
+				hash = _paddingRightProperty.hash(_paddingRight, hash);
+			if (_paddingBottom)
+				hash = _paddingBottomProperty.hash(_paddingBottom, hash);
+			if (_columnCount)
+				hash = _columnCountProperty.hash(_columnCount, hash);
+			if (_columnWidth)
+				hash = _columnWidthProperty.hash(_columnWidth, hash);
+			if (_firstBaselineOffset)
+				hash = _firstBaselineOffsetProperty.hash(_firstBaselineOffset, hash);
+			if (_verticalAlign)
+				hash = _verticalAlignProperty.hash(_verticalAlign, hash);
+			if (_blockProgression)
+				hash = _blockProgressionProperty.hash(_blockProgression, hash);
+			if (_lineBreak)
+				hash = _lineBreakProperty.hash(_lineBreak, hash);
+
+			return hash;
+		}
+
+		static private var _defaults:TextLayoutFormat;
+		/**
+		 * Returns a TextLayoutFormat object with default settings.
+		 * This function always returns the same object.
+		 * 
+		 * @return a singleton instance of ITextLayoutFormat that is populated with default values.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function get defaultFormat():ITextLayoutFormat
+		{
+			if (_defaults == null)
+			{
+				_defaults = new TextLayoutFormat();
+				Property.defaultsAllHelper(_description,_defaults);
+				_defaultFormatHash = _defaults.hash(0);
+			}
+			return _defaults;
+		}
+		static private var _defaultFormatHash:uint;
+		/** @private */
+		static tlf_internal function getDefaultFormatHash():uint
+		{
+			defaultFormat;
+			return _defaultFormatHash;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatInc.as b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatInc.as
new file mode 100755
index 0000000..5356d98
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatInc.as
@@ -0,0 +1,1259 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+////////////////////////////////////////////////////////////////////////////////
+		public function get color():*
+		{
+			return _formatValueHolder ? _formatValueHolder.color : undefined;
+		}
+		public function set color(colorValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().color = colorValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Background color of the text (adopts default value if undefined during cascade). Can be either the constant value  <code>BackgroundColor.TRANSPARENT</code>, or a hexadecimal value that specifies the three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green.
+		 * <p>Legal values as a string are flashx.textLayout.formats.BackgroundColor.TRANSPARENT, flashx.textLayout.formats.FormatValue.INHERIT and uints from 0x0 to 0xffffffff.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TRANSPARENT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BackgroundColor
+		 */
+		public function get backgroundColor():*
+		{
+			return _formatValueHolder ? _formatValueHolder.backgroundColor : undefined;
+		}
+		public function set backgroundColor(backgroundColorValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().backgroundColor = backgroundColorValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * If <code>true</code>, applies strikethrough, a line drawn through the middle of the text.
+		 * <p>Legal values are true, false and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of false.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineThrough():*
+		{
+			return _formatValueHolder ? _formatValueHolder.lineThrough : undefined;
+		}
+		public function set lineThrough(lineThroughValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().lineThrough = lineThroughValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Alpha (transparency) value for the text. A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with <code>textAlpha</code> set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textAlpha():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textAlpha : undefined;
+		}
+		public function set textAlpha(textAlphaValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textAlpha = textAlphaValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Alpha (transparency) value for the background (adopts default value if undefined during cascade). A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with alpha set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get backgroundAlpha():*
+		{
+			return _formatValueHolder ? _formatValueHolder.backgroundAlpha : undefined;
+		}
+		public function set backgroundAlpha(backgroundAlphaValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().backgroundAlpha = backgroundAlphaValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The size of the text in pixels.
+		 * <p>Legal values are numbers from 1 to 720 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 12.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontSize():*
+		{
+			return _formatValueHolder ? _formatValueHolder.fontSize : undefined;
+		}
+		public function set fontSize(fontSizeValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().fontSize = fontSizeValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Amount to shift the baseline from the <code>dominantBaseline</code> value. Units are in pixels, or a percentage of <code>fontSize</code> (in which case, enter a string value, like 140%).  Positive values shift the line up for horizontal text (right for vertical) and negative values shift it down for horizontal (left for vertical). 
+		 * <p>Legal values are flashx.textLayout.formats.BaselineShift.SUPERSCRIPT, flashx.textLayout.formats.BaselineShift.SUBSCRIPT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineShift
+		 */
+		public function get baselineShift():*
+		{
+			return _formatValueHolder ? _formatValueHolder.baselineShift : undefined;
+		}
+		public function set baselineShift(baselineShiftValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().baselineShift = baselineShiftValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the left of each character. If kerning is enabled, the <code>trackingLeft</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingLeft</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingLeft():*
+		{
+			return _formatValueHolder ? _formatValueHolder.trackingLeft : undefined;
+		}
+		public function set trackingLeft(trackingLeftValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().trackingLeft = trackingLeftValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the right of each character.  If kerning is enabled, the <code>trackingRight</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingRight</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingRight():*
+		{
+			return _formatValueHolder ? _formatValueHolder.trackingRight : undefined;
+		}
+		public function set trackingRight(trackingRightValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().trackingRight = trackingRightValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Leading controls for the text. The distance from the baseline of the previous or the next line (based on <code>LeadingModel</code>) to the baseline of the current line is equal to the maximum amount of the leading applied to any character in the line. This is either a number or a percent.  If specifying a percent, enter a string value, like 140%.<p><img src='../../../images/textLayout_lineHeight1.jpg' alt='lineHeight1' /><img src='../../../images/textLayout_lineHeight2.jpg' alt='lineHeight2' /></p>
+		 * <p>Legal values as a number are from -720 to 720.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 120%.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineHeight():*
+		{
+			return _formatValueHolder ? _formatValueHolder.lineHeight : undefined;
+		}
+		public function set lineHeight(lineHeightValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().lineHeight = lineHeightValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls where lines are allowed to break when breaking wrapping text into multiple lines. Set to <code>BreakOpportunity.AUTO</code> to break text normally. Set to <code>BreakOpportunity.NONE</code> to <em>not</em> break the text unless the text would overrun the measure and there are no other places to break the line. Set to <code>BreakOpportunity.ANY</code> to allow the line to break anywhere, rather than just between words. Set to <code>BreakOpportunity.ALL</code> to have each typographic cluster put on a separate line (useful for text on a path).
+		 * <p>Legal values are flash.text.engine.BreakOpportunity.ALL, flash.text.engine.BreakOpportunity.ANY, flash.text.engine.BreakOpportunity.AUTO, flash.text.engine.BreakOpportunity.NONE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.BreakOpportunity
+		 */
+		public function get breakOpportunity():*
+		{
+			return _formatValueHolder ? _formatValueHolder.breakOpportunity : undefined;
+		}
+		public function set breakOpportunity(breakOpportunityValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().breakOpportunity = breakOpportunityValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of digit case used for this text. Setting the value to <code>DigitCase.OLD_STYLE</code> approximates lowercase letterforms with varying ascenders and descenders. The figures are proportionally spaced. This style is only available in selected typefaces, most commonly in a supplemental or expert font. The <code>DigitCase.LINING</code> setting has all-cap height and is typically monospaced to line up in charts.<p><img src='../../../images/textLayout_digitcase.gif' alt='digitCase' /></p>
+		 * <p>Legal values are flash.text.engine.DigitCase.DEFAULT, flash.text.engine.DigitCase.LINING, flash.text.engine.DigitCase.OLD_STYLE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitCase
+		 */
+		public function get digitCase():*
+		{
+			return _formatValueHolder ? _formatValueHolder.digitCase : undefined;
+		}
+		public function set digitCase(digitCaseValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().digitCase = digitCaseValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Type of digit width used for this text. This can be <code>DigitWidth.PROPORTIONAL</code>, which looks best for individual numbers, or <code>DigitWidth.TABULAR</code>, which works best for numbers in tables, charts, and vertical rows.<p><img src='../../../images/textLayout_digitwidth.gif' alt='digitWidth' /></p>
+		 * <p>Legal values are flash.text.engine.DigitWidth.DEFAULT, flash.text.engine.DigitWidth.PROPORTIONAL, flash.text.engine.DigitWidth.TABULAR, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitWidth
+		 */
+		public function get digitWidth():*
+		{
+			return _formatValueHolder ? _formatValueHolder.digitWidth : undefined;
+		}
+		public function set digitWidth(digitWidthValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().digitWidth = digitWidthValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies which element baseline snaps to the <code>alignmentBaseline</code> to determine the vertical position of the element on the line. A value of <code>TextBaseline.AUTO</code> selects the dominant baseline based on the <code>locale</code> property of the parent paragraph.  For Japanese and Chinese, the selected baseline value is <code>TextBaseline.IDEOGRAPHIC_CENTER</code>; for all others it is <code>TextBaseline.ROMAN</code>. These baseline choices are determined by the choice of font and the font size.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO, flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get dominantBaseline():*
+		{
+			return _formatValueHolder ? _formatValueHolder.dominantBaseline : undefined;
+		}
+		public function set dominantBaseline(dominantBaselineValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().dominantBaseline = dominantBaselineValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Kerning adjusts the pixels between certain character pairs to improve readability. Kerning is supported for all fonts with kerning tables.
+		 * <p>Legal values are flash.text.engine.Kerning.ON, flash.text.engine.Kerning.OFF, flash.text.engine.Kerning.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.Kerning
+		 */
+		public function get kerning():*
+		{
+			return _formatValueHolder ? _formatValueHolder.kerning : undefined;
+		}
+		public function set kerning(kerningValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().kerning = kerningValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls which of the ligatures that are defined in the font may be used in the text. The ligatures that appear for each of these settings is dependent on the font. A ligature occurs where two or more letter-forms are joined as a single glyph. Ligatures usually replace consecutive characters sharing common components, such as the letter pairs 'fi', 'fl', or 'ae'. They are used with both Latin and Non-Latin character sets. The ligatures enabled by the values of the LigatureLevel class - <code>MINIMUM</code>, <code>COMMON</code>, <code>UNCOMMON</code>, and <code>EXOTIC</code> - are additive. Each value enables a new set of ligatures, but also includes those of the previous types.<p><b>Note: </b>When working with Arabic or Syriac fonts, <code>ligatureLevel</code> must be set to MINIMUM or above.</p><p><img src='../../../images/textLayout_ligatures.png' alt='ligatureLevel' /></p>
+		 * <p>Legal values are flash.text.engine.LigatureLevel.MINIMUM, flash.text.engine.LigatureLevel.COMMON, flash.text.engine.LigatureLevel.UNCOMMON, flash.text.engine.LigatureLevel.EXOTIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COMMON.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.LigatureLevel
+		 */
+		public function get ligatureLevel():*
+		{
+			return _formatValueHolder ? _formatValueHolder.ligatureLevel : undefined;
+		}
+		public function set ligatureLevel(ligatureLevelValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().ligatureLevel = ligatureLevelValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the baseline to which the dominant baseline aligns. For example, if you set <code>dominantBaseline</code> to ASCENT, setting <code>alignmentBaseline</code> to DESCENT aligns the top of the text with the DESCENT baseline, or below the line.  The largest element in the line generally determines the baselines.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of USE_DOMINANT_BASELINE.</p>
+		 * @includeExample examples\TextLayoutFormat_alignmentBaselineExample.as -noswf
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get alignmentBaseline():*
+		{
+			return _formatValueHolder ? _formatValueHolder.alignmentBaseline : undefined;
+		}
+		public function set alignmentBaseline(alignmentBaselineValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().alignmentBaseline = alignmentBaselineValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The locale of the text. Controls case transformations and shaping. Standard locale identifiers as described in Unicode Technical Standard #35 are used. For example en, en_US and en-US are all English, ja is Japanese. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of en.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get locale():*
+		{
+			return _formatValueHolder ? _formatValueHolder.locale : undefined;
+		}
+		public function set locale(localeValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().locale = localeValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of typographic case used for this text. Here are some examples:<p><img src='../../../images/textLayout_typographiccase.png' alt='typographicCase' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.TLFTypographicCase.DEFAULT, flashx.textLayout.formats.TLFTypographicCase.CAPS_TO_SMALL_CAPS, flashx.textLayout.formats.TLFTypographicCase.UPPERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TLFTypographicCase
+		 */
+		public function get typographicCase():*
+		{
+			return _formatValueHolder ? _formatValueHolder.typographicCase : undefined;
+		}
+		public function set typographicCase(typographicCaseValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().typographicCase = typographicCaseValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 *  The name of the font to use, or a comma-separated list of font names. The Flash runtime renders the element with the first available font in the list. For example Arial, Helvetica, _sans causes the player to search for Arial, then Helvetica if Arial is not found, then _sans if neither is found.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of Arial.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontFamily():*
+		{
+			return _formatValueHolder ? _formatValueHolder.fontFamily : undefined;
+		}
+		public function set fontFamily(fontFamilyValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().fontFamily = fontFamilyValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Decoration on text. Use to apply underlining; default is none.
+		 * <p>Legal values are flashx.textLayout.formats.TextDecoration.NONE, flashx.textLayout.formats.TextDecoration.UNDERLINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NONE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextDecoration
+		 */
+		public function get textDecoration():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textDecoration : undefined;
+		}
+		public function set textDecoration(textDecorationValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textDecoration = textDecorationValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Weight of text. May be <code>FontWeight.NORMAL</code> for use in plain text, or <code>FontWeight.BOLD</code>. Applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontWeight.NORMAL, flash.text.engine.FontWeight.BOLD, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontWeight
+		 */
+		public function get fontWeight():*
+		{
+			return _formatValueHolder ? _formatValueHolder.fontWeight : undefined;
+		}
+		public function set fontWeight(fontWeightValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().fontWeight = fontWeightValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Style of text. May be <code>FontPosture.NORMAL</code>, for use in plain text, or <code>FontPosture.ITALIC</code> for italic. This property applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontPosture.NORMAL, flash.text.engine.FontPosture.ITALIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontPosture
+		 */
+		public function get fontStyle():*
+		{
+			return _formatValueHolder ? _formatValueHolder.fontStyle : undefined;
+		}
+		public function set fontStyle(fontStyleValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().fontStyle = fontStyleValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Collapses or preserves whitespace when importing text into a TextFlow. <code>WhiteSpaceCollapse.PRESERVE</code> retains all whitespace characters. <code>WhiteSpaceCollapse.COLLAPSE</code> removes newlines, tabs, and leading or trailing spaces within a block of imported text. Line break tags (<br/>) and Unicode line separator characters are retained.
+		 * <p>Legal values are flashx.textLayout.formats.WhiteSpaceCollapse.PRESERVE, flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COLLAPSE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.WhiteSpaceCollapse
+		 */
+		public function get whiteSpaceCollapse():*
+		{
+			return _formatValueHolder ? _formatValueHolder.whiteSpaceCollapse : undefined;
+		}
+		public function set whiteSpaceCollapse(whiteSpaceCollapseValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().whiteSpaceCollapse = whiteSpaceCollapseValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The rendering mode used for this text.  Applies only to embedded fonts (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>).
+		 * <p>Legal values are flash.text.engine.RenderingMode.NORMAL, flash.text.engine.RenderingMode.CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of CFF.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.RenderingMode
+		 */
+		public function get renderingMode():*
+		{
+			return _formatValueHolder ? _formatValueHolder.renderingMode : undefined;
+		}
+		public function set renderingMode(renderingModeValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().renderingMode = renderingModeValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of CFF hinting used for this text. CFF hinting determines whether the Flash runtime forces strong horizontal stems to fit to a sub pixel grid or not. This property applies only if the <code>renderingMode</code> property is set to <code>RenderingMode.CFF</code>, and the font is embedded (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>). At small screen sizes, hinting produces a clear, legible text for human readers.
+		 * <p>Legal values are flash.text.engine.CFFHinting.NONE, flash.text.engine.CFFHinting.HORIZONTAL_STEM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of HORIZONTAL_STEM.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.CFFHinting
+		 */
+		public function get cffHinting():*
+		{
+			return _formatValueHolder ? _formatValueHolder.cffHinting : undefined;
+		}
+		public function set cffHinting(cffHintingValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().cffHinting = cffHintingValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Font lookup to use. Specifying <code>FontLookup.DEVICE</code> uses the fonts installed on the system that is running the SWF file. Device fonts result in a smaller movie size, but text is not always rendered the same across different systems and platforms. Specifying <code>FontLookup.EMBEDDED_CFF</code> uses font outlines embedded in the published SWF file. Embedded fonts increase the size of the SWF file (sometimes dramatically), but text is consistently displayed in the chosen font.
+		 * <p>Legal values are flash.text.engine.FontLookup.DEVICE, flash.text.engine.FontLookup.EMBEDDED_CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEVICE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontLookup
+		 */
+		public function get fontLookup():*
+		{
+			return _formatValueHolder ? _formatValueHolder.fontLookup : undefined;
+		}
+		public function set fontLookup(fontLookupValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().fontLookup = fontLookupValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Determines the number of degrees to rotate this text.
+		 * <p>Legal values are flash.text.engine.TextRotation.ROTATE_0, flash.text.engine.TextRotation.ROTATE_180, flash.text.engine.TextRotation.ROTATE_270, flash.text.engine.TextRotation.ROTATE_90, flash.text.engine.TextRotation.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextRotation
+		 */
+		public function get textRotation():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textRotation : undefined;
+		}
+		public function set textRotation(textRotationValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textRotation = textRotationValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the first line of the paragraph.
+		 * A negative indent will push the line into the margin, and possibly out of the container.
+		 * <p>Legal values are numbers from -1000 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textIndent():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textIndent : undefined;
+		}
+		public function set textIndent(textIndentValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textIndent = textIndentValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's start edge. Refers to the left edge in left-to-right text and the right edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphStartIndent():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paragraphStartIndent : undefined;
+		}
+		public function set paragraphStartIndent(paragraphStartIndentValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paragraphStartIndent = paragraphStartIndentValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's end edge. Refers to the right edge in left-to-right text and the left edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphEndIndent():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paragraphEndIndent : undefined;
+		}
+		public function set paragraphEndIndent(paragraphEndIndentValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paragraphEndIndent = paragraphEndIndentValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies the amount of space, in pixels, to leave before the paragraph. 
+		 * Collapses in tandem with <code>paragraphSpaceAfter</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceBefore():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paragraphSpaceBefore : undefined;
+		}
+		public function set paragraphSpaceBefore(paragraphSpaceBeforeValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paragraphSpaceBefore = paragraphSpaceBeforeValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies the amount of space, in pixels, to leave after the paragraph.
+		 * Collapses in tandem with  <code>paragraphSpaceBefore</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceAfter():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paragraphSpaceAfter : undefined;
+		}
+		public function set paragraphSpaceAfter(paragraphSpaceAfterValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paragraphSpaceAfter = paragraphSpaceAfterValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Alignment of lines in the paragraph relative to the container.
+		 * <code>TextAlign.LEFT</code> aligns lines along the left edge of the container. <code>TextAlign.RIGHT</code> aligns on the right edge. <code>TextAlign.CENTER</code> positions the line equidistant from the left and right edges. <code>TextAlign.JUSTIFY</code> spreads the lines out so they fill the space. <code>TextAlign.START</code> is equivalent to setting left in left-to-right text, or right in right-to-left text. <code>TextAlign.END</code> is equivalent to setting right in left-to-right text, or left in right-to-left text.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlign():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textAlign : undefined;
+		}
+		public function set textAlign(textAlignValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textAlign = textAlignValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Alignment of the last (or only) line in the paragraph relative to the container in justified text.
+		 * If <code>textAlign</code> is set to <code>TextAlign.JUSTIFY</code>, <code>textAlignLast</code> specifies how the last line (or only line, if this is a one line block) is aligned. Values are similar to <code>textAlign</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlignLast():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textAlignLast : undefined;
+		}
+		public function set textAlignLast(textAlignLastValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textAlignLast = textAlignLastValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies options for justifying text.
+		 * Default value is <code>TextJustify.INTER_WORD</code>, meaning that extra space is added to the space characters. <code>TextJustify.DISTRIBUTE</code> adds extra space to space characters and between individual letters. Used only in conjunction with a <code>justificationRule</code> value of <code>JustificationRule.SPACE</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextJustify.INTER_WORD, flashx.textLayout.formats.TextJustify.DISTRIBUTE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of INTER_WORD.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextJustify
+		 */
+		public function get textJustify():*
+		{
+			return _formatValueHolder ? _formatValueHolder.textJustify : undefined;
+		}
+		public function set textJustify(textJustifyValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().textJustify = textJustifyValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Rule used to justify text in a paragraph.
+		 * Default value is <code>FormatValue.AUTO</code>, which justifies text based on the paragraph's <code>locale</code> property. For all languages except Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustificationRule.SPACE</code>, which adds extra space to the space characters.  For Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustficationRule.EAST_ASIAN</code>. In part, justification changes the spacing of punctuation. In Roman text the comma and Japanese periods take a full character's width but in East Asian text only half of a character's width. Also, in the East Asian text the spacing between sequential punctuation marks becomes tighter, obeying traditional East Asian typographic conventions. Note, too, in the example below the leading that is applied to the second line of the paragraphs. In the East Asian version, the last two lines push left. In the Roman version, the second and following lines push left.<p><img src='../../../images/textLayout_justificationrule.png' alt='justificationRule' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.JustificationRule.EAST_ASIAN, flashx.textLayout.formats.JustificationRule.SPACE, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.JustificationRule
+		 */
+		public function get justificationRule():*
+		{
+			return _formatValueHolder ? _formatValueHolder.justificationRule : undefined;
+		}
+		public function set justificationRule(justificationRuleValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().justificationRule = justificationRuleValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * The style used for justification of the paragraph. Used only in conjunction with a <code>justificationRule</code> setting of <code>JustificationRule.EAST_ASIAN</code>.
+		 * Default value of <code>FormatValue.AUTO</code> is resolved to <code>JustificationStyle.PUSH_IN_KINSOKU</code> for all locales.  The constants defined by the JustificationStyle class specify options for handling kinsoku characters, which are Japanese characters that cannot appear at either the beginning or end of a line. If you want looser text, specify <code>JustificationStyle.PUSH-OUT-ONLY</code>. If you want behavior that is like what you get with the  <code>justificationRule</code> of <code>JustificationRule.SPACE</code>, use <code>JustificationStyle.PRIORITIZE-LEAST-ADJUSTMENT</code>.
+		 * <p>Legal values are flash.text.engine.JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT, flash.text.engine.JustificationStyle.PUSH_IN_KINSOKU, flash.text.engine.JustificationStyle.PUSH_OUT_ONLY, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.JustificationStyle
+		 */
+		public function get justificationStyle():*
+		{
+			return _formatValueHolder ? _formatValueHolder.justificationStyle : undefined;
+		}
+		public function set justificationStyle(justificationStyleValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().justificationStyle = justificationStyleValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the default bidirectional embedding level of the text in the text block. 
+		 * Left-to-right reading order, as in Latin-style scripts, or right-to-left reading order, as in Arabic or Hebrew. This property also affects column direction when it is applied at the container level. Columns can be either left-to-right or right-to-left, just like text. Below are some examples:<p><img src='../../../images/textLayout_direction.gif' alt='direction' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.Direction.LTR, flashx.textLayout.formats.Direction.RTL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of LTR.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.Direction
+		 */
+		public function get direction():*
+		{
+			return _formatValueHolder ? _formatValueHolder.direction : undefined;
+		}
+		public function set direction(directionValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().direction = directionValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the tab stops associated with the paragraph.
+		 * Setters can take an array of flashx.textLayout.formats.TabStopFormat, a condensed string representation, undefined, or <code>FormatValue.INHERIT</code>. The condensed string representation is always converted into an array of flashx.textLayout.formats.TabStopFormat. <p>The string-based format is a list of tab stops, where each tab stop is delimited by one or more spaces.</p><p>A tab stop takes the following form: &lt;alignment type&gt;&lt;alignment position&gt;|&lt;alignment token&gt;.</p><p>The alignment type is a single character, and can be S, E, C, or D (or lower-case equivalents). S or s for start, E or e for end, C or c for center, D or d for decimal. The alignment type is optional, and if its not specified will default to S.</p><p>The alignment position is a Number, and is specified according to FXG spec for Numbers (decimal or scientific notation). The alignment position is required.</p><p>The vertical bar is used to separate the alignment position from the alignment token, and should only be present if the alignment token is present.</p><p> The alignment token is optional if the alignment type is D, and should not be present if the alignment type is anything other than D. The alignment token may be any sequence of characters terminated by the space that ends the tab stop (for the last tab stop, the terminating space is optional; end of alignment token is implied). A space may be part of the alignment token if it is escaped with a backslash (\ ). A backslash may be part of the alignment token if it is escaped with another backslash (\\). If the alignment type is D, and the alignment token is not specified, it will take on the default value of null.</p><p>If no tab stops are specified, a tab action defaults to the end of the line.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get tabStops():*
+		{
+			return _formatValueHolder ? _formatValueHolder.tabStops : undefined;
+		}
+		public function set tabStops(tabStopsValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().tabStops = tabStopsValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the leading model, which is a combination of leading basis and leading direction.
+		 * Leading basis is the baseline to which the <code>lineHeight</code> property refers. Leading direction determines whether the <code>lineHeight</code> property refers to the distance of a line's baseline from that of the line before it or the line after it. The default value of <code>FormatValue.AUTO</code> is resolved based on the paragraph's <code>locale</code> property.  For Japanese and Chinese, it is <code>LeadingModel.IDEOGRAPHIC_TOP_DOWN</code> and for all others it is <code>LeadingModel.ROMAN_UP</code>.<p><strong>Leading Basis:</strong></p><p><img src='../../../images/textLayout_LB1.png' alt='leadingBasis1' />    <img src='../../../images/textLayout_LB2.png' alt='leadingBasis2' />    <img src='../../../images/textLayout_LB3.png' alt='leadingBasis3' /></p><p><strong>Leading Direction:</strong></p><p><img src='../../../images/textLayout_LD1.png' alt='leadingDirection1' />    <img src='../../../images/textLayout_LD2.png' alt='leadingDirection2' />    <img src='../../../images/textLayout_LD3.png' alt='leadingDirection3' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.LeadingModel.ROMAN_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_DOWN, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_DOWN, flashx.textLayout.formats.LeadingModel.APPROXIMATE_TEXT_FIELD, flashx.textLayout.formats.LeadingModel.ASCENT_DESCENT_UP, flashx.textLayout.formats.LeadingModel.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LeadingModel
+		 */
+		public function get leadingModel():*
+		{
+			return _formatValueHolder ? _formatValueHolder.leadingModel : undefined;
+		}
+		public function set leadingModel(leadingModelValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().leadingModel = leadingModelValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the amount of gutter space, in pixels, to leave between the columns (adopts default value if undefined during cascade).
+		 * Value is a Number
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 20.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get columnGap():*
+		{
+			return _formatValueHolder ? _formatValueHolder.columnGap : undefined;
+		}
+		public function set columnGap(columnGapValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().columnGap = columnGapValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Left inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the left edge of the container and the text.  Value is a Number.<p> With vertical text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the end of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingLeft():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paddingLeft : undefined;
+		}
+		public function set paddingLeft(paddingLeftValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paddingLeft = paddingLeftValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Top inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the top edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingTop():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paddingTop : undefined;
+		}
+		public function set paddingTop(paddingTopValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paddingTop = paddingTopValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Right inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the right edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingRight():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paddingRight : undefined;
+		}
+		public function set paddingRight(paddingRightValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paddingRight = paddingRightValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Botttom inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the bottom edge of the container and the text.  Value is a Number. <p> With horizontal text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the bottom of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingBottom():*
+		{
+			return _formatValueHolder ? _formatValueHolder.paddingBottom : undefined;
+		}
+		public function set paddingBottom(paddingBottomValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().paddingBottom = paddingBottomValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Number of text columns (adopts default value if undefined during cascade).
+		 * The column number overrides the  other column settings. Value is an integer, or <code>FormatValue.AUTO</code> if unspecified. If <code>columnCount</code> is not specified,<code>columnWidth</code> is used to create as many columns as can fit in the container.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and from ints from 1 to 50.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnCount():*
+		{
+			return _formatValueHolder ? _formatValueHolder.columnCount : undefined;
+		}
+		public function set columnCount(columnCountValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().columnCount = columnCountValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Column width in pixels (adopts default value if undefined during cascade).
+		 * If you specify the width of the columns, but not the count, TextLayout will create as many columns of that width as possible, given the  container width and <code>columnGap</code> settings. Any remainder space is left after the last column. Value is a Number.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 8000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnWidth():*
+		{
+			return _formatValueHolder ? _formatValueHolder.columnWidth : undefined;
+		}
+		public function set columnWidth(columnWidthValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().columnWidth = columnWidthValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the baseline position of the first line in the container. Which baseline this property refers to depends on the container-level locale.  For Japanese and Chinese, it is <code>TextBaseline.IDEOGRAPHIC_BOTTOM</code>; for all others it is <code>TextBaseline.ROMAN</code>.
+		 * The offset from the top inset (or right inset if <code>blockProgression</code> is RL) of the container to the baseline of the first line can be either <code>BaselineOffset.ASCENT</code>, meaning equal to the ascent of the line, <code>BaselineOffset.LINE_HEIGHT</code>, meaning equal to the height of that first line, or any fixed-value number to specify an absolute distance. <code>BaselineOffset.AUTO</code> aligns the ascent of the line with the container top inset.<p><img src='../../../images/textLayout_FBO1.png' alt='firstBaselineOffset1' /><img src='../../../images/textLayout_FBO2.png' alt='firstBaselineOffset2' /><img src='../../../images/textLayout_FBO3.png' alt='firstBaselineOffset3' /><img src='../../../images/textLayout_FBO4.png' alt='firstBaselineOffset4' /></p>
+		 * <p>Legal values as a string are flashx.textLayout.formats.BaselineOffset.AUTO, flashx.textLayout.formats.BaselineOffset.ASCENT, flashx.textLayout.formats.BaselineOffset.LINE_HEIGHT, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineOffset
+		 */
+		public function get firstBaselineOffset():*
+		{
+			return _formatValueHolder ? _formatValueHolder.firstBaselineOffset : undefined;
+		}
+		public function set firstBaselineOffset(firstBaselineOffsetValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().firstBaselineOffset = firstBaselineOffsetValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Vertical alignment or justification (adopts default value if undefined during cascade).
+		 * Determines how TextFlow elements align within the container.
+		 * <p>Legal values are flashx.textLayout.formats.VerticalAlign.TOP, flashx.textLayout.formats.VerticalAlign.MIDDLE, flashx.textLayout.formats.VerticalAlign.BOTTOM, flashx.textLayout.formats.VerticalAlign.JUSTIFY, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TOP.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.VerticalAlign
+		 */
+		public function get verticalAlign():*
+		{
+			return _formatValueHolder ? _formatValueHolder.verticalAlign : undefined;
+		}
+		public function set verticalAlign(verticalAlignValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().verticalAlign = verticalAlignValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies a vertical or horizontal progression of line placement.
+		 * Lines are either placed top-to-bottom (<code>BlockProgression.TB</code>, used for horizontal text) or right-to-left (<code>BlockProgression.RL</code>, used for vertical text).
+		 * <p>Legal values are flashx.textLayout.formats.BlockProgression.RL, flashx.textLayout.formats.BlockProgression.TB, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of TB.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BlockProgression
+		 */
+		public function get blockProgression():*
+		{
+			return _formatValueHolder ? _formatValueHolder.blockProgression : undefined;
+		}
+		public function set blockProgression(blockProgressionValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().blockProgression = blockProgressionValue;
+			formatChanged();
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls word wrapping within the container (adopts default value if undefined during cascade).
+		 * Text in the container may be set to fit the width of the container (<code>LineBreak.TO_FIT</code>), or can be set to break only at explicit return or line feed characters (<code>LineBreak.EXPLICIT</code>).
+		 * <p>Legal values are flashx.textLayout.formats.LineBreak.EXPLICIT, flashx.textLayout.formats.LineBreak.TO_FIT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TO_FIT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LineBreak
+		 */
+		public function get lineBreak():*
+		{
+			return _formatValueHolder ? _formatValueHolder.lineBreak : undefined;
+		}
+		public function set lineBreak(lineBreakValue:*):void
+		{
+			writableTextLayoutFormatValueHolder().lineBreak = lineBreakValue;
+			formatChanged();
+		}
diff --git a/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatValueHolder.as b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatValueHolder.as
new file mode 100755
index 0000000..5c336ac
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/TextLayoutFormatValueHolder.as
@@ -0,0 +1,1457 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** @private */
+	public class TextLayoutFormatValueHolder implements ITextLayoutFormat
+	{
+		private var _coreStyles:Object;
+
+		public function TextLayoutFormatValueHolder(initialValues:ITextLayoutFormat = null)
+		{
+			initialize(initialValues);
+		}
+
+		private function initialize(initialValues:ITextLayoutFormat):void
+		{
+			if (initialValues)
+			{
+				var holder:TextLayoutFormatValueHolder = initialValues as TextLayoutFormatValueHolder;
+				if (holder)
+				{
+					for (var s:String in holder.coreStyles)
+						writableCoreStyles()[s] = holder.coreStyles[s];
+				}
+				else
+				{
+					for each (var prop:Property in TextLayoutFormat.description)
+					{
+						var val:* = initialValues[prop.name];
+						if (val !== undefined)
+							writableCoreStyles()[prop.name] = val;
+					}
+				}
+			}
+		}
+
+		private function writableCoreStyles():Object
+		{
+			if (_coreStyles == null)
+				_coreStyles = new Object();
+			return _coreStyles;
+		}
+
+		public function get coreStyles():Object
+		{ return _coreStyles; }
+		public function set coreStyles(val:Object):void
+		{ _coreStyles = val; }
+
+		private function getCoreStyle(styleProp:String):*
+		{ return _coreStyles ? _coreStyles[styleProp] : undefined; }
+		private function setCoreStyle(styleProp:Property,currValue:*,newValue:*):void
+		{
+			newValue = styleProp.setHelper(currValue,newValue);
+			if (newValue !== undefined)
+				writableCoreStyles()[styleProp.name] = newValue;
+			else if (_coreStyles)
+				delete _coreStyles[styleProp.name];
+		}
+
+		public function hash(hash:uint):uint
+		{
+			for (var s:String in coreStyles)
+				hash = TextLayoutFormat.description[s].hash(coreStyles[s],hash);
+			return hash;
+		}
+
+		public function set format(incoming:ITextLayoutFormat):void
+		{
+			if (incoming == null)
+			{
+				coreStyles = null;
+				return;
+			}
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+				coreStyles = holder.coreStyles ? Property.shallowCopy(holder.coreStyles) : null;
+				return;
+			}
+
+			coreStyles = null;
+			var val:*;
+			if ((val = incoming.color) !== undefined)
+				this.color = val;
+			if ((val = incoming.backgroundColor) !== undefined)
+				this.backgroundColor = val;
+			if ((val = incoming.lineThrough) !== undefined)
+				this.lineThrough = val;
+			if ((val = incoming.textAlpha) !== undefined)
+				this.textAlpha = val;
+			if ((val = incoming.backgroundAlpha) !== undefined)
+				this.backgroundAlpha = val;
+			if ((val = incoming.fontSize) !== undefined)
+				this.fontSize = val;
+			if ((val = incoming.baselineShift) !== undefined)
+				this.baselineShift = val;
+			if ((val = incoming.trackingLeft) !== undefined)
+				this.trackingLeft = val;
+			if ((val = incoming.trackingRight) !== undefined)
+				this.trackingRight = val;
+			if ((val = incoming.lineHeight) !== undefined)
+				this.lineHeight = val;
+			if ((val = incoming.breakOpportunity) !== undefined)
+				this.breakOpportunity = val;
+			if ((val = incoming.digitCase) !== undefined)
+				this.digitCase = val;
+			if ((val = incoming.digitWidth) !== undefined)
+				this.digitWidth = val;
+			if ((val = incoming.dominantBaseline) !== undefined)
+				this.dominantBaseline = val;
+			if ((val = incoming.kerning) !== undefined)
+				this.kerning = val;
+			if ((val = incoming.ligatureLevel) !== undefined)
+				this.ligatureLevel = val;
+			if ((val = incoming.alignmentBaseline) !== undefined)
+				this.alignmentBaseline = val;
+			if ((val = incoming.locale) !== undefined)
+				this.locale = val;
+			if ((val = incoming.typographicCase) !== undefined)
+				this.typographicCase = val;
+			if ((val = incoming.fontFamily) !== undefined)
+				this.fontFamily = val;
+			if ((val = incoming.textDecoration) !== undefined)
+				this.textDecoration = val;
+			if ((val = incoming.fontWeight) !== undefined)
+				this.fontWeight = val;
+			if ((val = incoming.fontStyle) !== undefined)
+				this.fontStyle = val;
+			if ((val = incoming.whiteSpaceCollapse) !== undefined)
+				this.whiteSpaceCollapse = val;
+			if ((val = incoming.renderingMode) !== undefined)
+				this.renderingMode = val;
+			if ((val = incoming.cffHinting) !== undefined)
+				this.cffHinting = val;
+			if ((val = incoming.fontLookup) !== undefined)
+				this.fontLookup = val;
+			if ((val = incoming.textRotation) !== undefined)
+				this.textRotation = val;
+			if ((val = incoming.textIndent) !== undefined)
+				this.textIndent = val;
+			if ((val = incoming.paragraphStartIndent) !== undefined)
+				this.paragraphStartIndent = val;
+			if ((val = incoming.paragraphEndIndent) !== undefined)
+				this.paragraphEndIndent = val;
+			if ((val = incoming.paragraphSpaceBefore) !== undefined)
+				this.paragraphSpaceBefore = val;
+			if ((val = incoming.paragraphSpaceAfter) !== undefined)
+				this.paragraphSpaceAfter = val;
+			if ((val = incoming.textAlign) !== undefined)
+				this.textAlign = val;
+			if ((val = incoming.textAlignLast) !== undefined)
+				this.textAlignLast = val;
+			if ((val = incoming.textJustify) !== undefined)
+				this.textJustify = val;
+			if ((val = incoming.justificationRule) !== undefined)
+				this.justificationRule = val;
+			if ((val = incoming.justificationStyle) !== undefined)
+				this.justificationStyle = val;
+			if ((val = incoming.direction) !== undefined)
+				this.direction = val;
+			if ((val = incoming.tabStops) !== undefined)
+				this.tabStops = val;
+			if ((val = incoming.leadingModel) !== undefined)
+				this.leadingModel = val;
+			if ((val = incoming.columnGap) !== undefined)
+				this.columnGap = val;
+			if ((val = incoming.paddingLeft) !== undefined)
+				this.paddingLeft = val;
+			if ((val = incoming.paddingTop) !== undefined)
+				this.paddingTop = val;
+			if ((val = incoming.paddingRight) !== undefined)
+				this.paddingRight = val;
+			if ((val = incoming.paddingBottom) !== undefined)
+				this.paddingBottom = val;
+			if ((val = incoming.columnCount) !== undefined)
+				this.columnCount = val;
+			if ((val = incoming.columnWidth) !== undefined)
+				this.columnWidth = val;
+			if ((val = incoming.firstBaselineOffset) !== undefined)
+				this.firstBaselineOffset = val;
+			if ((val = incoming.verticalAlign) !== undefined)
+				this.verticalAlign = val;
+			if ((val = incoming.blockProgression) !== undefined)
+				this.blockProgression = val;
+			if ((val = incoming.lineBreak) !== undefined)
+				this.lineBreak = val;
+		}
+
+		public function concat(incoming:ITextLayoutFormat):void
+		{
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+				for (var key:String in holder.coreStyles)
+				{
+					this[key] = TextLayoutFormat.description[key].concatHelper(this[key],holder.coreStyles[key]);
+				}
+				return;
+			}
+
+			this.color = TextLayoutFormat.colorProperty.concatHelper(this.color, incoming.color);
+			this.backgroundColor = TextLayoutFormat.backgroundColorProperty.concatHelper(this.backgroundColor, incoming.backgroundColor);
+			this.lineThrough = TextLayoutFormat.lineThroughProperty.concatHelper(this.lineThrough, incoming.lineThrough);
+			this.textAlpha = TextLayoutFormat.textAlphaProperty.concatHelper(this.textAlpha, incoming.textAlpha);
+			this.backgroundAlpha = TextLayoutFormat.backgroundAlphaProperty.concatHelper(this.backgroundAlpha, incoming.backgroundAlpha);
+			this.fontSize = TextLayoutFormat.fontSizeProperty.concatHelper(this.fontSize, incoming.fontSize);
+			this.baselineShift = TextLayoutFormat.baselineShiftProperty.concatHelper(this.baselineShift, incoming.baselineShift);
+			this.trackingLeft = TextLayoutFormat.trackingLeftProperty.concatHelper(this.trackingLeft, incoming.trackingLeft);
+			this.trackingRight = TextLayoutFormat.trackingRightProperty.concatHelper(this.trackingRight, incoming.trackingRight);
+			this.lineHeight = TextLayoutFormat.lineHeightProperty.concatHelper(this.lineHeight, incoming.lineHeight);
+			this.breakOpportunity = TextLayoutFormat.breakOpportunityProperty.concatHelper(this.breakOpportunity, incoming.breakOpportunity);
+			this.digitCase = TextLayoutFormat.digitCaseProperty.concatHelper(this.digitCase, incoming.digitCase);
+			this.digitWidth = TextLayoutFormat.digitWidthProperty.concatHelper(this.digitWidth, incoming.digitWidth);
+			this.dominantBaseline = TextLayoutFormat.dominantBaselineProperty.concatHelper(this.dominantBaseline, incoming.dominantBaseline);
+			this.kerning = TextLayoutFormat.kerningProperty.concatHelper(this.kerning, incoming.kerning);
+			this.ligatureLevel = TextLayoutFormat.ligatureLevelProperty.concatHelper(this.ligatureLevel, incoming.ligatureLevel);
+			this.alignmentBaseline = TextLayoutFormat.alignmentBaselineProperty.concatHelper(this.alignmentBaseline, incoming.alignmentBaseline);
+			this.locale = TextLayoutFormat.localeProperty.concatHelper(this.locale, incoming.locale);
+			this.typographicCase = TextLayoutFormat.typographicCaseProperty.concatHelper(this.typographicCase, incoming.typographicCase);
+			this.fontFamily = TextLayoutFormat.fontFamilyProperty.concatHelper(this.fontFamily, incoming.fontFamily);
+			this.textDecoration = TextLayoutFormat.textDecorationProperty.concatHelper(this.textDecoration, incoming.textDecoration);
+			this.fontWeight = TextLayoutFormat.fontWeightProperty.concatHelper(this.fontWeight, incoming.fontWeight);
+			this.fontStyle = TextLayoutFormat.fontStyleProperty.concatHelper(this.fontStyle, incoming.fontStyle);
+			this.whiteSpaceCollapse = TextLayoutFormat.whiteSpaceCollapseProperty.concatHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse);
+			this.renderingMode = TextLayoutFormat.renderingModeProperty.concatHelper(this.renderingMode, incoming.renderingMode);
+			this.cffHinting = TextLayoutFormat.cffHintingProperty.concatHelper(this.cffHinting, incoming.cffHinting);
+			this.fontLookup = TextLayoutFormat.fontLookupProperty.concatHelper(this.fontLookup, incoming.fontLookup);
+			this.textRotation = TextLayoutFormat.textRotationProperty.concatHelper(this.textRotation, incoming.textRotation);
+			this.textIndent = TextLayoutFormat.textIndentProperty.concatHelper(this.textIndent, incoming.textIndent);
+			this.paragraphStartIndent = TextLayoutFormat.paragraphStartIndentProperty.concatHelper(this.paragraphStartIndent, incoming.paragraphStartIndent);
+			this.paragraphEndIndent = TextLayoutFormat.paragraphEndIndentProperty.concatHelper(this.paragraphEndIndent, incoming.paragraphEndIndent);
+			this.paragraphSpaceBefore = TextLayoutFormat.paragraphSpaceBeforeProperty.concatHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore);
+			this.paragraphSpaceAfter = TextLayoutFormat.paragraphSpaceAfterProperty.concatHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter);
+			this.textAlign = TextLayoutFormat.textAlignProperty.concatHelper(this.textAlign, incoming.textAlign);
+			this.textAlignLast = TextLayoutFormat.textAlignLastProperty.concatHelper(this.textAlignLast, incoming.textAlignLast);
+			this.textJustify = TextLayoutFormat.textJustifyProperty.concatHelper(this.textJustify, incoming.textJustify);
+			this.justificationRule = TextLayoutFormat.justificationRuleProperty.concatHelper(this.justificationRule, incoming.justificationRule);
+			this.justificationStyle = TextLayoutFormat.justificationStyleProperty.concatHelper(this.justificationStyle, incoming.justificationStyle);
+			this.direction = TextLayoutFormat.directionProperty.concatHelper(this.direction, incoming.direction);
+			this.tabStops = TextLayoutFormat.tabStopsProperty.concatHelper(this.tabStops, incoming.tabStops);
+			this.leadingModel = TextLayoutFormat.leadingModelProperty.concatHelper(this.leadingModel, incoming.leadingModel);
+			this.columnGap = TextLayoutFormat.columnGapProperty.concatHelper(this.columnGap, incoming.columnGap);
+			this.paddingLeft = TextLayoutFormat.paddingLeftProperty.concatHelper(this.paddingLeft, incoming.paddingLeft);
+			this.paddingTop = TextLayoutFormat.paddingTopProperty.concatHelper(this.paddingTop, incoming.paddingTop);
+			this.paddingRight = TextLayoutFormat.paddingRightProperty.concatHelper(this.paddingRight, incoming.paddingRight);
+			this.paddingBottom = TextLayoutFormat.paddingBottomProperty.concatHelper(this.paddingBottom, incoming.paddingBottom);
+			this.columnCount = TextLayoutFormat.columnCountProperty.concatHelper(this.columnCount, incoming.columnCount);
+			this.columnWidth = TextLayoutFormat.columnWidthProperty.concatHelper(this.columnWidth, incoming.columnWidth);
+			this.firstBaselineOffset = TextLayoutFormat.firstBaselineOffsetProperty.concatHelper(this.firstBaselineOffset, incoming.firstBaselineOffset);
+			this.verticalAlign = TextLayoutFormat.verticalAlignProperty.concatHelper(this.verticalAlign, incoming.verticalAlign);
+			this.blockProgression = TextLayoutFormat.blockProgressionProperty.concatHelper(this.blockProgression, incoming.blockProgression);
+			this.lineBreak = TextLayoutFormat.lineBreakProperty.concatHelper(this.lineBreak, incoming.lineBreak);
+		}
+
+		public function concatInheritOnly(incoming:ITextLayoutFormat):void
+		{
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+				for (var key:String in holder.coreStyles)
+				{
+					this[key] = TextLayoutFormat.description[key].concatInheritOnlyHelper(this[key],holder.coreStyles[key]);
+				}
+				return;
+			}
+
+			this.color = TextLayoutFormat.colorProperty.concatInheritOnlyHelper(this.color, incoming.color);
+			this.backgroundColor = TextLayoutFormat.backgroundColorProperty.concatInheritOnlyHelper(this.backgroundColor, incoming.backgroundColor);
+			this.lineThrough = TextLayoutFormat.lineThroughProperty.concatInheritOnlyHelper(this.lineThrough, incoming.lineThrough);
+			this.textAlpha = TextLayoutFormat.textAlphaProperty.concatInheritOnlyHelper(this.textAlpha, incoming.textAlpha);
+			this.backgroundAlpha = TextLayoutFormat.backgroundAlphaProperty.concatInheritOnlyHelper(this.backgroundAlpha, incoming.backgroundAlpha);
+			this.fontSize = TextLayoutFormat.fontSizeProperty.concatInheritOnlyHelper(this.fontSize, incoming.fontSize);
+			this.baselineShift = TextLayoutFormat.baselineShiftProperty.concatInheritOnlyHelper(this.baselineShift, incoming.baselineShift);
+			this.trackingLeft = TextLayoutFormat.trackingLeftProperty.concatInheritOnlyHelper(this.trackingLeft, incoming.trackingLeft);
+			this.trackingRight = TextLayoutFormat.trackingRightProperty.concatInheritOnlyHelper(this.trackingRight, incoming.trackingRight);
+			this.lineHeight = TextLayoutFormat.lineHeightProperty.concatInheritOnlyHelper(this.lineHeight, incoming.lineHeight);
+			this.breakOpportunity = TextLayoutFormat.breakOpportunityProperty.concatInheritOnlyHelper(this.breakOpportunity, incoming.breakOpportunity);
+			this.digitCase = TextLayoutFormat.digitCaseProperty.concatInheritOnlyHelper(this.digitCase, incoming.digitCase);
+			this.digitWidth = TextLayoutFormat.digitWidthProperty.concatInheritOnlyHelper(this.digitWidth, incoming.digitWidth);
+			this.dominantBaseline = TextLayoutFormat.dominantBaselineProperty.concatInheritOnlyHelper(this.dominantBaseline, incoming.dominantBaseline);
+			this.kerning = TextLayoutFormat.kerningProperty.concatInheritOnlyHelper(this.kerning, incoming.kerning);
+			this.ligatureLevel = TextLayoutFormat.ligatureLevelProperty.concatInheritOnlyHelper(this.ligatureLevel, incoming.ligatureLevel);
+			this.alignmentBaseline = TextLayoutFormat.alignmentBaselineProperty.concatInheritOnlyHelper(this.alignmentBaseline, incoming.alignmentBaseline);
+			this.locale = TextLayoutFormat.localeProperty.concatInheritOnlyHelper(this.locale, incoming.locale);
+			this.typographicCase = TextLayoutFormat.typographicCaseProperty.concatInheritOnlyHelper(this.typographicCase, incoming.typographicCase);
+			this.fontFamily = TextLayoutFormat.fontFamilyProperty.concatInheritOnlyHelper(this.fontFamily, incoming.fontFamily);
+			this.textDecoration = TextLayoutFormat.textDecorationProperty.concatInheritOnlyHelper(this.textDecoration, incoming.textDecoration);
+			this.fontWeight = TextLayoutFormat.fontWeightProperty.concatInheritOnlyHelper(this.fontWeight, incoming.fontWeight);
+			this.fontStyle = TextLayoutFormat.fontStyleProperty.concatInheritOnlyHelper(this.fontStyle, incoming.fontStyle);
+			this.whiteSpaceCollapse = TextLayoutFormat.whiteSpaceCollapseProperty.concatInheritOnlyHelper(this.whiteSpaceCollapse, incoming.whiteSpaceCollapse);
+			this.renderingMode = TextLayoutFormat.renderingModeProperty.concatInheritOnlyHelper(this.renderingMode, incoming.renderingMode);
+			this.cffHinting = TextLayoutFormat.cffHintingProperty.concatInheritOnlyHelper(this.cffHinting, incoming.cffHinting);
+			this.fontLookup = TextLayoutFormat.fontLookupProperty.concatInheritOnlyHelper(this.fontLookup, incoming.fontLookup);
+			this.textRotation = TextLayoutFormat.textRotationProperty.concatInheritOnlyHelper(this.textRotation, incoming.textRotation);
+			this.textIndent = TextLayoutFormat.textIndentProperty.concatInheritOnlyHelper(this.textIndent, incoming.textIndent);
+			this.paragraphStartIndent = TextLayoutFormat.paragraphStartIndentProperty.concatInheritOnlyHelper(this.paragraphStartIndent, incoming.paragraphStartIndent);
+			this.paragraphEndIndent = TextLayoutFormat.paragraphEndIndentProperty.concatInheritOnlyHelper(this.paragraphEndIndent, incoming.paragraphEndIndent);
+			this.paragraphSpaceBefore = TextLayoutFormat.paragraphSpaceBeforeProperty.concatInheritOnlyHelper(this.paragraphSpaceBefore, incoming.paragraphSpaceBefore);
+			this.paragraphSpaceAfter = TextLayoutFormat.paragraphSpaceAfterProperty.concatInheritOnlyHelper(this.paragraphSpaceAfter, incoming.paragraphSpaceAfter);
+			this.textAlign = TextLayoutFormat.textAlignProperty.concatInheritOnlyHelper(this.textAlign, incoming.textAlign);
+			this.textAlignLast = TextLayoutFormat.textAlignLastProperty.concatInheritOnlyHelper(this.textAlignLast, incoming.textAlignLast);
+			this.textJustify = TextLayoutFormat.textJustifyProperty.concatInheritOnlyHelper(this.textJustify, incoming.textJustify);
+			this.justificationRule = TextLayoutFormat.justificationRuleProperty.concatInheritOnlyHelper(this.justificationRule, incoming.justificationRule);
+			this.justificationStyle = TextLayoutFormat.justificationStyleProperty.concatInheritOnlyHelper(this.justificationStyle, incoming.justificationStyle);
+			this.direction = TextLayoutFormat.directionProperty.concatInheritOnlyHelper(this.direction, incoming.direction);
+			this.tabStops = TextLayoutFormat.tabStopsProperty.concatInheritOnlyHelper(this.tabStops, incoming.tabStops);
+			this.leadingModel = TextLayoutFormat.leadingModelProperty.concatInheritOnlyHelper(this.leadingModel, incoming.leadingModel);
+			this.columnGap = TextLayoutFormat.columnGapProperty.concatInheritOnlyHelper(this.columnGap, incoming.columnGap);
+			this.paddingLeft = TextLayoutFormat.paddingLeftProperty.concatInheritOnlyHelper(this.paddingLeft, incoming.paddingLeft);
+			this.paddingTop = TextLayoutFormat.paddingTopProperty.concatInheritOnlyHelper(this.paddingTop, incoming.paddingTop);
+			this.paddingRight = TextLayoutFormat.paddingRightProperty.concatInheritOnlyHelper(this.paddingRight, incoming.paddingRight);
+			this.paddingBottom = TextLayoutFormat.paddingBottomProperty.concatInheritOnlyHelper(this.paddingBottom, incoming.paddingBottom);
+			this.columnCount = TextLayoutFormat.columnCountProperty.concatInheritOnlyHelper(this.columnCount, incoming.columnCount);
+			this.columnWidth = TextLayoutFormat.columnWidthProperty.concatInheritOnlyHelper(this.columnWidth, incoming.columnWidth);
+			this.firstBaselineOffset = TextLayoutFormat.firstBaselineOffsetProperty.concatInheritOnlyHelper(this.firstBaselineOffset, incoming.firstBaselineOffset);
+			this.verticalAlign = TextLayoutFormat.verticalAlignProperty.concatInheritOnlyHelper(this.verticalAlign, incoming.verticalAlign);
+			this.blockProgression = TextLayoutFormat.blockProgressionProperty.concatInheritOnlyHelper(this.blockProgression, incoming.blockProgression);
+			this.lineBreak = TextLayoutFormat.lineBreakProperty.concatInheritOnlyHelper(this.lineBreak, incoming.lineBreak);
+		}
+
+		public function apply(incoming:ITextLayoutFormat):void
+		{
+			var holder:TextLayoutFormatValueHolder = incoming as TextLayoutFormatValueHolder;
+			if (holder)
+			{
+				for (var key:String in holder.coreStyles)
+				{
+					CONFIG::debug { assert(holder.coreStyles[key] !== undefined,"bad value in apply"); }
+					this[key] = holder.coreStyles[key];
+				}
+				return;
+			}
+
+			var val:*;
+			if ((val = incoming.color) !== undefined)
+				this.color = val;
+			if ((val = incoming.backgroundColor) !== undefined)
+				this.backgroundColor = val;
+			if ((val = incoming.lineThrough) !== undefined)
+				this.lineThrough = val;
+			if ((val = incoming.textAlpha) !== undefined)
+				this.textAlpha = val;
+			if ((val = incoming.backgroundAlpha) !== undefined)
+				this.backgroundAlpha = val;
+			if ((val = incoming.fontSize) !== undefined)
+				this.fontSize = val;
+			if ((val = incoming.baselineShift) !== undefined)
+				this.baselineShift = val;
+			if ((val = incoming.trackingLeft) !== undefined)
+				this.trackingLeft = val;
+			if ((val = incoming.trackingRight) !== undefined)
+				this.trackingRight = val;
+			if ((val = incoming.lineHeight) !== undefined)
+				this.lineHeight = val;
+			if ((val = incoming.breakOpportunity) !== undefined)
+				this.breakOpportunity = val;
+			if ((val = incoming.digitCase) !== undefined)
+				this.digitCase = val;
+			if ((val = incoming.digitWidth) !== undefined)
+				this.digitWidth = val;
+			if ((val = incoming.dominantBaseline) !== undefined)
+				this.dominantBaseline = val;
+			if ((val = incoming.kerning) !== undefined)
+				this.kerning = val;
+			if ((val = incoming.ligatureLevel) !== undefined)
+				this.ligatureLevel = val;
+			if ((val = incoming.alignmentBaseline) !== undefined)
+				this.alignmentBaseline = val;
+			if ((val = incoming.locale) !== undefined)
+				this.locale = val;
+			if ((val = incoming.typographicCase) !== undefined)
+				this.typographicCase = val;
+			if ((val = incoming.fontFamily) !== undefined)
+				this.fontFamily = val;
+			if ((val = incoming.textDecoration) !== undefined)
+				this.textDecoration = val;
+			if ((val = incoming.fontWeight) !== undefined)
+				this.fontWeight = val;
+			if ((val = incoming.fontStyle) !== undefined)
+				this.fontStyle = val;
+			if ((val = incoming.whiteSpaceCollapse) !== undefined)
+				this.whiteSpaceCollapse = val;
+			if ((val = incoming.renderingMode) !== undefined)
+				this.renderingMode = val;
+			if ((val = incoming.cffHinting) !== undefined)
+				this.cffHinting = val;
+			if ((val = incoming.fontLookup) !== undefined)
+				this.fontLookup = val;
+			if ((val = incoming.textRotation) !== undefined)
+				this.textRotation = val;
+			if ((val = incoming.textIndent) !== undefined)
+				this.textIndent = val;
+			if ((val = incoming.paragraphStartIndent) !== undefined)
+				this.paragraphStartIndent = val;
+			if ((val = incoming.paragraphEndIndent) !== undefined)
+				this.paragraphEndIndent = val;
+			if ((val = incoming.paragraphSpaceBefore) !== undefined)
+				this.paragraphSpaceBefore = val;
+			if ((val = incoming.paragraphSpaceAfter) !== undefined)
+				this.paragraphSpaceAfter = val;
+			if ((val = incoming.textAlign) !== undefined)
+				this.textAlign = val;
+			if ((val = incoming.textAlignLast) !== undefined)
+				this.textAlignLast = val;
+			if ((val = incoming.textJustify) !== undefined)
+				this.textJustify = val;
+			if ((val = incoming.justificationRule) !== undefined)
+				this.justificationRule = val;
+			if ((val = incoming.justificationStyle) !== undefined)
+				this.justificationStyle = val;
+			if ((val = incoming.direction) !== undefined)
+				this.direction = val;
+			if ((val = incoming.tabStops) !== undefined)
+				this.tabStops = val;
+			if ((val = incoming.leadingModel) !== undefined)
+				this.leadingModel = val;
+			if ((val = incoming.columnGap) !== undefined)
+				this.columnGap = val;
+			if ((val = incoming.paddingLeft) !== undefined)
+				this.paddingLeft = val;
+			if ((val = incoming.paddingTop) !== undefined)
+				this.paddingTop = val;
+			if ((val = incoming.paddingRight) !== undefined)
+				this.paddingRight = val;
+			if ((val = incoming.paddingBottom) !== undefined)
+				this.paddingBottom = val;
+			if ((val = incoming.columnCount) !== undefined)
+				this.columnCount = val;
+			if ((val = incoming.columnWidth) !== undefined)
+				this.columnWidth = val;
+			if ((val = incoming.firstBaselineOffset) !== undefined)
+				this.firstBaselineOffset = val;
+			if ((val = incoming.verticalAlign) !== undefined)
+				this.verticalAlign = val;
+			if ((val = incoming.blockProgression) !== undefined)
+				this.blockProgression = val;
+			if ((val = incoming.lineBreak) !== undefined)
+				this.lineBreak = val;
+		}
+
+		/**
+		 * TextLayoutFormat:
+		 * Color of the text. A hexadecimal number that specifies three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get color():*
+		{ return getCoreStyle("color"); }
+		public function set color(value:*):void
+		{ setCoreStyle(TextLayoutFormat.colorProperty,color,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Background color of the text (adopts default value if undefined during cascade). Can be either the constant value  <code>BackgroundColor.TRANSPARENT</code>, or a hexadecimal value that specifies the three 8-bit RGB (red, green, blue) values; for example, 0xFF0000 is red and 0x00FF00 is green.
+		 * <p>Legal values as a string are flashx.textLayout.formats.BackgroundColor.TRANSPARENT, flashx.textLayout.formats.FormatValue.INHERIT and uints from 0x0 to 0xffffffff.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TRANSPARENT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BackgroundColor
+		 */
+		public function get backgroundColor():*
+		{ return getCoreStyle("backgroundColor"); }
+		public function set backgroundColor(value:*):void
+		{ setCoreStyle(TextLayoutFormat.backgroundColorProperty,backgroundColor,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * If <code>true</code>, applies strikethrough, a line drawn through the middle of the text.
+		 * <p>Legal values are true, false and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of false.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineThrough():*
+		{ return getCoreStyle("lineThrough"); }
+		public function set lineThrough(value:*):void
+		{ setCoreStyle(TextLayoutFormat.lineThroughProperty,lineThrough,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Alpha (transparency) value for the text. A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with <code>textAlpha</code> set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textAlpha():*
+		{ return getCoreStyle("textAlpha"); }
+		public function set textAlpha(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textAlphaProperty,textAlpha,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Alpha (transparency) value for the background (adopts default value if undefined during cascade). A value of 0 is fully transparent, and a value of 1 is fully opaque. Display objects with alpha set to 0 are active, even though they are invisible.
+		 * <p>Legal values are numbers from 0 to 1 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 1.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get backgroundAlpha():*
+		{ return getCoreStyle("backgroundAlpha"); }
+		public function set backgroundAlpha(value:*):void
+		{ setCoreStyle(TextLayoutFormat.backgroundAlphaProperty,backgroundAlpha,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The size of the text in pixels.
+		 * <p>Legal values are numbers from 1 to 720 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 12.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontSize():*
+		{ return getCoreStyle("fontSize"); }
+		public function set fontSize(value:*):void
+		{ setCoreStyle(TextLayoutFormat.fontSizeProperty,fontSize,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Amount to shift the baseline from the <code>dominantBaseline</code> value. Units are in pixels, or a percentage of <code>fontSize</code> (in which case, enter a string value, like 140%).  Positive values shift the line up for horizontal text (right for vertical) and negative values shift it down for horizontal (left for vertical). 
+		 * <p>Legal values are flashx.textLayout.formats.BaselineShift.SUPERSCRIPT, flashx.textLayout.formats.BaselineShift.SUBSCRIPT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineShift
+		 */
+		public function get baselineShift():*
+		{ return getCoreStyle("baselineShift"); }
+		public function set baselineShift(value:*):void
+		{ setCoreStyle(TextLayoutFormat.baselineShiftProperty,baselineShift,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the left of each character. If kerning is enabled, the <code>trackingLeft</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingLeft</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingLeft():*
+		{ return getCoreStyle("trackingLeft"); }
+		public function set trackingLeft(value:*):void
+		{ setCoreStyle(TextLayoutFormat.trackingLeftProperty,trackingLeft,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Number in pixels (or percent of <code>fontSize</code>, like 120%) indicating the amount of tracking (manual kerning) to be applied to the right of each character.  If kerning is enabled, the <code>trackingRight</code> value is added to the values in the kerning table for the font. If kerning is disabled, the <code>trackingRight</code> value is used as a manual kerning value. Supports both positive and negative values. 
+		 * <p>Legal values as a number are from -1000 to 1000.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get trackingRight():*
+		{ return getCoreStyle("trackingRight"); }
+		public function set trackingRight(value:*):void
+		{ setCoreStyle(TextLayoutFormat.trackingRightProperty,trackingRight,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Leading controls for the text. The distance from the baseline of the previous or the next line (based on <code>LeadingModel</code>) to the baseline of the current line is equal to the maximum amount of the leading applied to any character in the line. This is either a number or a percent.  If specifying a percent, enter a string value, like 140%.<p><img src='../../../images/textLayout_lineHeight1.jpg' alt='lineHeight1' /><img src='../../../images/textLayout_lineHeight2.jpg' alt='lineHeight2' /></p>
+		 * <p>Legal values as a number are from -720 to 720.</p>
+		 * <p>Legal values as a percent are numbers from -1000% to 1000%.</p>
+		 * <p>Legal values include flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 120%.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get lineHeight():*
+		{ return getCoreStyle("lineHeight"); }
+		public function set lineHeight(value:*):void
+		{ setCoreStyle(TextLayoutFormat.lineHeightProperty,lineHeight,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls where lines are allowed to break when breaking wrapping text into multiple lines. Set to <code>BreakOpportunity.AUTO</code> to break text normally. Set to <code>BreakOpportunity.NONE</code> to <em>not</em> break the text unless the text would overrun the measure and there are no other places to break the line. Set to <code>BreakOpportunity.ANY</code> to allow the line to break anywhere, rather than just between words. Set to <code>BreakOpportunity.ALL</code> to have each typographic cluster put on a separate line (useful for text on a path).
+		 * <p>Legal values are flash.text.engine.BreakOpportunity.ALL, flash.text.engine.BreakOpportunity.ANY, flash.text.engine.BreakOpportunity.AUTO, flash.text.engine.BreakOpportunity.NONE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.BreakOpportunity
+		 */
+		public function get breakOpportunity():*
+		{ return getCoreStyle("breakOpportunity"); }
+		public function set breakOpportunity(value:*):void
+		{ setCoreStyle(TextLayoutFormat.breakOpportunityProperty,breakOpportunity,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of digit case used for this text. Setting the value to <code>DigitCase.OLD_STYLE</code> approximates lowercase letterforms with varying ascenders and descenders. The figures are proportionally spaced. This style is only available in selected typefaces, most commonly in a supplemental or expert font. The <code>DigitCase.LINING</code> setting has all-cap height and is typically monospaced to line up in charts.<p><img src='../../../images/textLayout_digitcase.gif' alt='digitCase' /></p>
+		 * <p>Legal values are flash.text.engine.DigitCase.DEFAULT, flash.text.engine.DigitCase.LINING, flash.text.engine.DigitCase.OLD_STYLE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitCase
+		 */
+		public function get digitCase():*
+		{ return getCoreStyle("digitCase"); }
+		public function set digitCase(value:*):void
+		{ setCoreStyle(TextLayoutFormat.digitCaseProperty,digitCase,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Type of digit width used for this text. This can be <code>DigitWidth.PROPORTIONAL</code>, which looks best for individual numbers, or <code>DigitWidth.TABULAR</code>, which works best for numbers in tables, charts, and vertical rows.<p><img src='../../../images/textLayout_digitwidth.gif' alt='digitWidth' /></p>
+		 * <p>Legal values are flash.text.engine.DigitWidth.DEFAULT, flash.text.engine.DigitWidth.PROPORTIONAL, flash.text.engine.DigitWidth.TABULAR, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.DigitWidth
+		 */
+		public function get digitWidth():*
+		{ return getCoreStyle("digitWidth"); }
+		public function set digitWidth(value:*):void
+		{ setCoreStyle(TextLayoutFormat.digitWidthProperty,digitWidth,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies which element baseline snaps to the <code>alignmentBaseline</code> to determine the vertical position of the element on the line. A value of <code>TextBaseline.AUTO</code> selects the dominant baseline based on the <code>locale</code> property of the parent paragraph.  For Japanese and Chinese, the selected baseline value is <code>TextBaseline.IDEOGRAPHIC_CENTER</code>; for all others it is <code>TextBaseline.ROMAN</code>. These baseline choices are determined by the choice of font and the font size.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.FormatValue.AUTO, flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get dominantBaseline():*
+		{ return getCoreStyle("dominantBaseline"); }
+		public function set dominantBaseline(value:*):void
+		{ setCoreStyle(TextLayoutFormat.dominantBaselineProperty,dominantBaseline,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Kerning adjusts the pixels between certain character pairs to improve readability. Kerning is supported for all fonts with kerning tables.
+		 * <p>Legal values are flash.text.engine.Kerning.ON, flash.text.engine.Kerning.OFF, flash.text.engine.Kerning.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.Kerning
+		 */
+		public function get kerning():*
+		{ return getCoreStyle("kerning"); }
+		public function set kerning(value:*):void
+		{ setCoreStyle(TextLayoutFormat.kerningProperty,kerning,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls which of the ligatures that are defined in the font may be used in the text. The ligatures that appear for each of these settings is dependent on the font. A ligature occurs where two or more letter-forms are joined as a single glyph. Ligatures usually replace consecutive characters sharing common components, such as the letter pairs 'fi', 'fl', or 'ae'. They are used with both Latin and Non-Latin character sets. The ligatures enabled by the values of the LigatureLevel class - <code>MINIMUM</code>, <code>COMMON</code>, <code>UNCOMMON</code>, and <code>EXOTIC</code> - are additive. Each value enables a new set of ligatures, but also includes those of the previous types.<p><b>Note: </b>When working with Arabic or Syriac fonts, <code>ligatureLevel</code> must be set to MINIMUM or above.</p><p><img src='../../../images/textLayout_ligatures.png' alt='ligatureLevel' /></p>
+		 * <p>Legal values are flash.text.engine.LigatureLevel.MINIMUM, flash.text.engine.LigatureLevel.COMMON, flash.text.engine.LigatureLevel.UNCOMMON, flash.text.engine.LigatureLevel.EXOTIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COMMON.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.LigatureLevel
+		 */
+		public function get ligatureLevel():*
+		{ return getCoreStyle("ligatureLevel"); }
+		public function set ligatureLevel(value:*):void
+		{ setCoreStyle(TextLayoutFormat.ligatureLevelProperty,ligatureLevel,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the baseline to which the dominant baseline aligns. For example, if you set <code>dominantBaseline</code> to ASCENT, setting <code>alignmentBaseline</code> to DESCENT aligns the top of the text with the DESCENT baseline, or below the line.  The largest element in the line generally determines the baselines.<p><img src='../../../images/textLayout_baselines.jpg' alt='baselines' /></p>
+		 * <p>Legal values are flash.text.engine.TextBaseline.ROMAN, flash.text.engine.TextBaseline.ASCENT, flash.text.engine.TextBaseline.DESCENT, flash.text.engine.TextBaseline.IDEOGRAPHIC_TOP, flash.text.engine.TextBaseline.IDEOGRAPHIC_CENTER, flash.text.engine.TextBaseline.IDEOGRAPHIC_BOTTOM, flash.text.engine.TextBaseline.USE_DOMINANT_BASELINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of USE_DOMINANT_BASELINE.</p>
+		 * @includeExample examples\TextLayoutFormat_alignmentBaselineExample.as -noswf
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextBaseline
+		 */
+		public function get alignmentBaseline():*
+		{ return getCoreStyle("alignmentBaseline"); }
+		public function set alignmentBaseline(value:*):void
+		{ setCoreStyle(TextLayoutFormat.alignmentBaselineProperty,alignmentBaseline,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The locale of the text. Controls case transformations and shaping. Standard locale identifiers as described in Unicode Technical Standard #35 are used. For example en, en_US and en-US are all English, ja is Japanese. 
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of en.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get locale():*
+		{ return getCoreStyle("locale"); }
+		public function set locale(value:*):void
+		{ setCoreStyle(TextLayoutFormat.localeProperty,locale,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of typographic case used for this text. Here are some examples:<p><img src='../../../images/textLayout_typographiccase.png' alt='typographicCase' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.TLFTypographicCase.DEFAULT, flashx.textLayout.formats.TLFTypographicCase.CAPS_TO_SMALL_CAPS, flashx.textLayout.formats.TLFTypographicCase.UPPERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE, flashx.textLayout.formats.TLFTypographicCase.LOWERCASE_TO_SMALL_CAPS, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEFAULT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TLFTypographicCase
+		 */
+		public function get typographicCase():*
+		{ return getCoreStyle("typographicCase"); }
+		public function set typographicCase(value:*):void
+		{ setCoreStyle(TextLayoutFormat.typographicCaseProperty,typographicCase,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 *  The name of the font to use, or a comma-separated list of font names. The Flash runtime renders the element with the first available font in the list. For example Arial, Helvetica, _sans causes the player to search for Arial, then Helvetica if Arial is not found, then _sans if neither is found.
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of Arial.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get fontFamily():*
+		{ return getCoreStyle("fontFamily"); }
+		public function set fontFamily(value:*):void
+		{ setCoreStyle(TextLayoutFormat.fontFamilyProperty,fontFamily,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Decoration on text. Use to apply underlining; default is none.
+		 * <p>Legal values are flashx.textLayout.formats.TextDecoration.NONE, flashx.textLayout.formats.TextDecoration.UNDERLINE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NONE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextDecoration
+		 */
+		public function get textDecoration():*
+		{ return getCoreStyle("textDecoration"); }
+		public function set textDecoration(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textDecorationProperty,textDecoration,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Weight of text. May be <code>FontWeight.NORMAL</code> for use in plain text, or <code>FontWeight.BOLD</code>. Applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontWeight.NORMAL, flash.text.engine.FontWeight.BOLD, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontWeight
+		 */
+		public function get fontWeight():*
+		{ return getCoreStyle("fontWeight"); }
+		public function set fontWeight(value:*):void
+		{ setCoreStyle(TextLayoutFormat.fontWeightProperty,fontWeight,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Style of text. May be <code>FontPosture.NORMAL</code>, for use in plain text, or <code>FontPosture.ITALIC</code> for italic. This property applies only to device fonts (<code>fontLookup</code> property is set to flash.text.engine.FontLookup.DEVICE).
+		 * <p>Legal values are flash.text.engine.FontPosture.NORMAL, flash.text.engine.FontPosture.ITALIC, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of NORMAL.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontPosture
+		 */
+		public function get fontStyle():*
+		{ return getCoreStyle("fontStyle"); }
+		public function set fontStyle(value:*):void
+		{ setCoreStyle(TextLayoutFormat.fontStyleProperty,fontStyle,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Collapses or preserves whitespace when importing text into a TextFlow. <code>WhiteSpaceCollapse.PRESERVE</code> retains all whitespace characters. <code>WhiteSpaceCollapse.COLLAPSE</code> removes newlines, tabs, and leading or trailing spaces within a block of imported text. Line break tags (<br/>) and Unicode line separator characters are retained.
+		 * <p>Legal values are flashx.textLayout.formats.WhiteSpaceCollapse.PRESERVE, flashx.textLayout.formats.WhiteSpaceCollapse.COLLAPSE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of COLLAPSE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.WhiteSpaceCollapse
+		 */
+		public function get whiteSpaceCollapse():*
+		{ return getCoreStyle("whiteSpaceCollapse"); }
+		public function set whiteSpaceCollapse(value:*):void
+		{ setCoreStyle(TextLayoutFormat.whiteSpaceCollapseProperty,whiteSpaceCollapse,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The rendering mode used for this text.  Applies only to embedded fonts (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>).
+		 * <p>Legal values are flash.text.engine.RenderingMode.NORMAL, flash.text.engine.RenderingMode.CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of CFF.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.RenderingMode
+		 */
+		public function get renderingMode():*
+		{ return getCoreStyle("renderingMode"); }
+		public function set renderingMode(value:*):void
+		{ setCoreStyle(TextLayoutFormat.renderingModeProperty,renderingMode,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The type of CFF hinting used for this text. CFF hinting determines whether the Flash runtime forces strong horizontal stems to fit to a sub pixel grid or not. This property applies only if the <code>renderingMode</code> property is set to <code>RenderingMode.CFF</code>, and the font is embedded (<code>fontLookup</code> property is set to <code>FontLookup.EMBEDDED_CFF</code>). At small screen sizes, hinting produces a clear, legible text for human readers.
+		 * <p>Legal values are flash.text.engine.CFFHinting.NONE, flash.text.engine.CFFHinting.HORIZONTAL_STEM, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of HORIZONTAL_STEM.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.CFFHinting
+		 */
+		public function get cffHinting():*
+		{ return getCoreStyle("cffHinting"); }
+		public function set cffHinting(value:*):void
+		{ setCoreStyle(TextLayoutFormat.cffHintingProperty,cffHinting,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Font lookup to use. Specifying <code>FontLookup.DEVICE</code> uses the fonts installed on the system that is running the SWF file. Device fonts result in a smaller movie size, but text is not always rendered the same across different systems and platforms. Specifying <code>FontLookup.EMBEDDED_CFF</code> uses font outlines embedded in the published SWF file. Embedded fonts increase the size of the SWF file (sometimes dramatically), but text is consistently displayed in the chosen font.
+		 * <p>Legal values are flash.text.engine.FontLookup.DEVICE, flash.text.engine.FontLookup.EMBEDDED_CFF, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of DEVICE.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.FontLookup
+		 */
+		public function get fontLookup():*
+		{ return getCoreStyle("fontLookup"); }
+		public function set fontLookup(value:*):void
+		{ setCoreStyle(TextLayoutFormat.fontLookupProperty,fontLookup,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Determines the number of degrees to rotate this text.
+		 * <p>Legal values are flash.text.engine.TextRotation.ROTATE_0, flash.text.engine.TextRotation.ROTATE_180, flash.text.engine.TextRotation.ROTATE_270, flash.text.engine.TextRotation.ROTATE_90, flash.text.engine.TextRotation.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.TextRotation
+		 */
+		public function get textRotation():*
+		{ return getCoreStyle("textRotation"); }
+		public function set textRotation(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textRotationProperty,textRotation,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the first line of the paragraph.
+		 * A negative indent will push the line into the margin, and possibly out of the container.
+		 * <p>Legal values are numbers from -1000 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get textIndent():*
+		{ return getCoreStyle("textIndent"); }
+		public function set textIndent(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textIndentProperty,textIndent,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's start edge. Refers to the left edge in left-to-right text and the right edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphStartIndent():*
+		{ return getCoreStyle("paragraphStartIndent"); }
+		public function set paragraphStartIndent(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paragraphStartIndentProperty,paragraphStartIndent,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies, in pixels, the amount to indent the paragraph's end edge. Refers to the right edge in left-to-right text and the left edge in right-to-left text. 
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphEndIndent():*
+		{ return getCoreStyle("paragraphEndIndent"); }
+		public function set paragraphEndIndent(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paragraphEndIndentProperty,paragraphEndIndent,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies the amount of space, in pixels, to leave before the paragraph. 
+		 * Collapses in tandem with <code>paragraphSpaceAfter</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceBefore():*
+		{ return getCoreStyle("paragraphSpaceBefore"); }
+		public function set paragraphSpaceBefore(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paragraphSpaceBeforeProperty,paragraphSpaceBefore,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * A Number that specifies the amount of space, in pixels, to leave after the paragraph.
+		 * Collapses in tandem with  <code>paragraphSpaceBefore</code>.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paragraphSpaceAfter():*
+		{ return getCoreStyle("paragraphSpaceAfter"); }
+		public function set paragraphSpaceAfter(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paragraphSpaceAfterProperty,paragraphSpaceAfter,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Alignment of lines in the paragraph relative to the container.
+		 * <code>TextAlign.LEFT</code> aligns lines along the left edge of the container. <code>TextAlign.RIGHT</code> aligns on the right edge. <code>TextAlign.CENTER</code> positions the line equidistant from the left and right edges. <code>TextAlign.JUSTIFY</code> spreads the lines out so they fill the space. <code>TextAlign.START</code> is equivalent to setting left in left-to-right text, or right in right-to-left text. <code>TextAlign.END</code> is equivalent to setting right in left-to-right text, or left in right-to-left text.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlign():*
+		{ return getCoreStyle("textAlign"); }
+		public function set textAlign(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textAlignProperty,textAlign,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Alignment of the last (or only) line in the paragraph relative to the container in justified text.
+		 * If <code>textAlign</code> is set to <code>TextAlign.JUSTIFY</code>, <code>textAlignLast</code> specifies how the last line (or only line, if this is a one line block) is aligned. Values are similar to <code>textAlign</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextAlign.LEFT, flashx.textLayout.formats.TextAlign.RIGHT, flashx.textLayout.formats.TextAlign.CENTER, flashx.textLayout.formats.TextAlign.JUSTIFY, flashx.textLayout.formats.TextAlign.START, flashx.textLayout.formats.TextAlign.END, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of START.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextAlign
+		 */
+		public function get textAlignLast():*
+		{ return getCoreStyle("textAlignLast"); }
+		public function set textAlignLast(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textAlignLastProperty,textAlignLast,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies options for justifying text.
+		 * Default value is <code>TextJustify.INTER_WORD</code>, meaning that extra space is added to the space characters. <code>TextJustify.DISTRIBUTE</code> adds extra space to space characters and between individual letters. Used only in conjunction with a <code>justificationRule</code> value of <code>JustificationRule.SPACE</code>.
+		 * <p>Legal values are flashx.textLayout.formats.TextJustify.INTER_WORD, flashx.textLayout.formats.TextJustify.DISTRIBUTE, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of INTER_WORD.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.TextJustify
+		 */
+		public function get textJustify():*
+		{ return getCoreStyle("textJustify"); }
+		public function set textJustify(value:*):void
+		{ setCoreStyle(TextLayoutFormat.textJustifyProperty,textJustify,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Rule used to justify text in a paragraph.
+		 * Default value is <code>FormatValue.AUTO</code>, which justifies text based on the paragraph's <code>locale</code> property. For all languages except Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustificationRule.SPACE</code>, which adds extra space to the space characters.  For Japanese and Chinese, <code>FormatValue.AUTO</code> becomes <code>JustficationRule.EAST_ASIAN</code>. In part, justification changes the spacing of punctuation. In Roman text the comma and Japanese periods take a full character's width but in East Asian text only half of a character's width. Also, in the East Asian text the spacing between sequential punctuation marks becomes tighter, obeying traditional East Asian typographic conventions. Note, too, in the example below the leading that is applied to the second line of the paragraphs. In the East Asian version, the last two lines push left. In the Roman version, the second and following lines push left.<p><img src='../../../images/textLayout_justificationrule.png' alt='justificationRule' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.JustificationRule.EAST_ASIAN, flashx.textLayout.formats.JustificationRule.SPACE, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.JustificationRule
+		 */
+		public function get justificationRule():*
+		{ return getCoreStyle("justificationRule"); }
+		public function set justificationRule(value:*):void
+		{ setCoreStyle(TextLayoutFormat.justificationRuleProperty,justificationRule,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * The style used for justification of the paragraph. Used only in conjunction with a <code>justificationRule</code> setting of <code>JustificationRule.EAST_ASIAN</code>.
+		 * Default value of <code>FormatValue.AUTO</code> is resolved to <code>JustificationStyle.PUSH_IN_KINSOKU</code> for all locales.  The constants defined by the JustificationStyle class specify options for handling kinsoku characters, which are Japanese characters that cannot appear at either the beginning or end of a line. If you want looser text, specify <code>JustificationStyle.PUSH-OUT-ONLY</code>. If you want behavior that is like what you get with the  <code>justificationRule</code> of <code>JustificationRule.SPACE</code>, use <code>JustificationStyle.PRIORITIZE-LEAST-ADJUSTMENT</code>.
+		 * <p>Legal values are flash.text.engine.JustificationStyle.PRIORITIZE_LEAST_ADJUSTMENT, flash.text.engine.JustificationStyle.PUSH_IN_KINSOKU, flash.text.engine.JustificationStyle.PUSH_OUT_ONLY, flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of flashx.textLayout.formats.FormatValue.AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flash.text.engine.JustificationStyle
+		 */
+		public function get justificationStyle():*
+		{ return getCoreStyle("justificationStyle"); }
+		public function set justificationStyle(value:*):void
+		{ setCoreStyle(TextLayoutFormat.justificationStyleProperty,justificationStyle,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the default bidirectional embedding level of the text in the text block. 
+		 * Left-to-right reading order, as in Latin-style scripts, or right-to-left reading order, as in Arabic or Hebrew. This property also affects column direction when it is applied at the container level. Columns can be either left-to-right or right-to-left, just like text. Below are some examples:<p><img src='../../../images/textLayout_direction.gif' alt='direction' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.Direction.LTR, flashx.textLayout.formats.Direction.RTL, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of LTR.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.Direction
+		 */
+		public function get direction():*
+		{ return getCoreStyle("direction"); }
+		public function set direction(value:*):void
+		{ setCoreStyle(TextLayoutFormat.directionProperty,direction,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the tab stops associated with the paragraph.
+		 * Setters can take an array of flashx.textLayout.formats.TabStopFormat, a condensed string representation, undefined, or <code>FormatValue.INHERIT</code>. The condensed string representation is always converted into an array of flashx.textLayout.formats.TabStopFormat. <p>The string-based format is a list of tab stops, where each tab stop is delimited by one or more spaces.</p><p>A tab stop takes the following form: &lt;alignment type&gt;&lt;alignment position&gt;|&lt;alignment token&gt;.</p><p>The alignment type is a single character, and can be S, E, C, or D (or lower-case equivalents). S or s for start, E or e for end, C or c for center, D or d for decimal. The alignment type is optional, and if its not specified will default to S.</p><p>The alignment position is a Number, and is specified according to FXG spec for Numbers (decimal or scientific notation). The alignment position is required.</p><p>The vertical bar is used to separate the alignment position from the alignment token, and should only be present if the alignment token is present.</p><p> The alignment token is optional if the alignment type is D, and should not be present if the alignment type is anything other than D. The alignment token may be any sequence of characters terminated by the space that ends the tab stop (for the last tab stop, the terminating space is optional; end of alignment token is implied). A space may be part of the alignment token if it is escaped with a backslash (\ ). A backslash may be part of the alignment token if it is escaped with another backslash (\\). If the alignment type is D, and the alignment token is not specified, it will take on the default value of null.</p><p>If no tab stops are specified, a tab action defaults to the end of the line.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of null.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get tabStops():*
+		{ return getCoreStyle("tabStops"); }
+		public function set tabStops(value:*):void
+		{ setCoreStyle(TextLayoutFormat.tabStopsProperty,tabStops,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the leading model, which is a combination of leading basis and leading direction.
+		 * Leading basis is the baseline to which the <code>lineHeight</code> property refers. Leading direction determines whether the <code>lineHeight</code> property refers to the distance of a line's baseline from that of the line before it or the line after it. The default value of <code>FormatValue.AUTO</code> is resolved based on the paragraph's <code>locale</code> property.  For Japanese and Chinese, it is <code>LeadingModel.IDEOGRAPHIC_TOP_DOWN</code> and for all others it is <code>LeadingModel.ROMAN_UP</code>.<p><strong>Leading Basis:</strong></p><p><img src='../../../images/textLayout_LB1.png' alt='leadingBasis1' />    <img src='../../../images/textLayout_LB2.png' alt='leadingBasis2' />    <img src='../../../images/textLayout_LB3.png' alt='leadingBasis3' /></p><p><strong>Leading Direction:</strong></p><p><img src='../../../images/textLayout_LD1.png' alt='leadingDirection1' />    <img src='../../../images/textLayout_LD2.png' alt='leadingDirection2' />    <img src='../../../images/textLayout_LD3.png' alt='leadingDirection3' /></p>
+		 * <p>Legal values are flashx.textLayout.formats.LeadingModel.ROMAN_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_UP, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_TOP_DOWN, flashx.textLayout.formats.LeadingModel.IDEOGRAPHIC_CENTER_DOWN, flashx.textLayout.formats.LeadingModel.APPROXIMATE_TEXT_FIELD, flashx.textLayout.formats.LeadingModel.ASCENT_DESCENT_UP, flashx.textLayout.formats.LeadingModel.AUTO, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LeadingModel
+		 */
+		public function get leadingModel():*
+		{ return getCoreStyle("leadingModel"); }
+		public function set leadingModel(value:*):void
+		{ setCoreStyle(TextLayoutFormat.leadingModelProperty,leadingModel,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the amount of gutter space, in pixels, to leave between the columns (adopts default value if undefined during cascade).
+		 * Value is a Number
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 20.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get columnGap():*
+		{ return getCoreStyle("columnGap"); }
+		public function set columnGap(value:*):void
+		{ setCoreStyle(TextLayoutFormat.columnGapProperty,columnGap,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Left inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the left edge of the container and the text.  Value is a Number.<p> With vertical text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the end of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingLeft():*
+		{ return getCoreStyle("paddingLeft"); }
+		public function set paddingLeft(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paddingLeftProperty,paddingLeft,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Top inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the top edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingTop():*
+		{ return getCoreStyle("paddingTop"); }
+		public function set paddingTop(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paddingTopProperty,paddingTop,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Right inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the right edge of the container and the text.  Value is a Number.
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingRight():*
+		{ return getCoreStyle("paddingRight"); }
+		public function set paddingRight(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paddingRightProperty,paddingRight,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Botttom inset in pixels (adopts default value if undefined during cascade).
+		 * Space between the bottom edge of the container and the text.  Value is a Number. <p> With horizontal text, in scrollable containers with multiple columns, the first and following columns will show the padding as blank space at the bottom of the container, but for the last column, if the text doesn't all fit, you may have to scroll in order to see the padding.</p>
+		 * <p>Legal values are numbers from 0 to 1000 and flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of 0.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function get paddingBottom():*
+		{ return getCoreStyle("paddingBottom"); }
+		public function set paddingBottom(value:*):void
+		{ setCoreStyle(TextLayoutFormat.paddingBottomProperty,paddingBottom,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Number of text columns (adopts default value if undefined during cascade).
+		 * The column number overrides the  other column settings. Value is an integer, or <code>FormatValue.AUTO</code> if unspecified. If <code>columnCount</code> is not specified,<code>columnWidth</code> is used to create as many columns as can fit in the container.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and from ints from 1 to 50.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnCount():*
+		{ return getCoreStyle("columnCount"); }
+		public function set columnCount(value:*):void
+		{ setCoreStyle(TextLayoutFormat.columnCountProperty,columnCount,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Column width in pixels (adopts default value if undefined during cascade).
+		 * If you specify the width of the columns, but not the count, TextLayout will create as many columns of that width as possible, given the  container width and <code>columnGap</code> settings. Any remainder space is left after the last column. Value is a Number.
+		 * <p>Legal values as a string are flashx.textLayout.formats.FormatValue.AUTO, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 8000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.FormatValue
+		 */
+		public function get columnWidth():*
+		{ return getCoreStyle("columnWidth"); }
+		public function set columnWidth(value:*):void
+		{ setCoreStyle(TextLayoutFormat.columnWidthProperty,columnWidth,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies the baseline position of the first line in the container. Which baseline this property refers to depends on the container-level locale.  For Japanese and Chinese, it is <code>TextBaseline.IDEOGRAPHIC_BOTTOM</code>; for all others it is <code>TextBaseline.ROMAN</code>.
+		 * The offset from the top inset (or right inset if <code>blockProgression</code> is RL) of the container to the baseline of the first line can be either <code>BaselineOffset.ASCENT</code>, meaning equal to the ascent of the line, <code>BaselineOffset.LINE_HEIGHT</code>, meaning equal to the height of that first line, or any fixed-value number to specify an absolute distance. <code>BaselineOffset.AUTO</code> aligns the ascent of the line with the container top inset.<p><img src='../../../images/textLayout_FBO1.png' alt='firstBaselineOffset1' /><img src='../../../images/textLayout_FBO2.png' alt='firstBaselineOffset2' /><img src='../../../images/textLayout_FBO3.png' alt='firstBaselineOffset3' /><img src='../../../images/textLayout_FBO4.png' alt='firstBaselineOffset4' /></p>
+		 * <p>Legal values as a string are flashx.textLayout.formats.BaselineOffset.AUTO, flashx.textLayout.formats.BaselineOffset.ASCENT, flashx.textLayout.formats.BaselineOffset.LINE_HEIGHT, flashx.textLayout.formats.FormatValue.INHERIT and numbers from 0 to 1000.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of AUTO.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BaselineOffset
+		 */
+		public function get firstBaselineOffset():*
+		{ return getCoreStyle("firstBaselineOffset"); }
+		public function set firstBaselineOffset(value:*):void
+		{ setCoreStyle(TextLayoutFormat.firstBaselineOffsetProperty,firstBaselineOffset,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Vertical alignment or justification (adopts default value if undefined during cascade).
+		 * Determines how TextFlow elements align within the container.
+		 * <p>Legal values are flashx.textLayout.formats.VerticalAlign.TOP, flashx.textLayout.formats.VerticalAlign.MIDDLE, flashx.textLayout.formats.VerticalAlign.BOTTOM, flashx.textLayout.formats.VerticalAlign.JUSTIFY, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TOP.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.VerticalAlign
+		 */
+		public function get verticalAlign():*
+		{ return getCoreStyle("verticalAlign"); }
+		public function set verticalAlign(value:*):void
+		{ setCoreStyle(TextLayoutFormat.verticalAlignProperty,verticalAlign,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Specifies a vertical or horizontal progression of line placement.
+		 * Lines are either placed top-to-bottom (<code>BlockProgression.TB</code>, used for horizontal text) or right-to-left (<code>BlockProgression.RL</code>, used for vertical text).
+		 * <p>Legal values are flashx.textLayout.formats.BlockProgression.RL, flashx.textLayout.formats.BlockProgression.TB, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will inherit its value from an ancestor. If no ancestor has set this property, it will have a value of TB.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.BlockProgression
+		 */
+		public function get blockProgression():*
+		{ return getCoreStyle("blockProgression"); }
+		public function set blockProgression(value:*):void
+		{ setCoreStyle(TextLayoutFormat.blockProgressionProperty,blockProgression,value); }
+
+		/**
+		 * TextLayoutFormat:
+		 * Controls word wrapping within the container (adopts default value if undefined during cascade).
+		 * Text in the container may be set to fit the width of the container (<code>LineBreak.TO_FIT</code>), or can be set to break only at explicit return or line feed characters (<code>LineBreak.EXPLICIT</code>).
+		 * <p>Legal values are flashx.textLayout.formats.LineBreak.EXPLICIT, flashx.textLayout.formats.LineBreak.TO_FIT, flashx.textLayout.formats.FormatValue.INHERIT.</p>
+		 * <p>Default value is undefined indicating not set.</p>
+		 * <p>If undefined during the cascade this property will have a value of TO_FIT.</p>
+		 * 
+		 * @throws RangeError when set value is not within range for this property
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * @see flashx.textLayout.formats.LineBreak
+		 */
+		public function get lineBreak():*
+		{ return getCoreStyle("lineBreak"); }
+		public function set lineBreak(value:*):void
+		{ setCoreStyle(TextLayoutFormat.lineBreakProperty,lineBreak,value); }
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/formats/VerticalAlign.as b/textLayout_core/src/flashx/textLayout/formats/VerticalAlign.as
new file mode 100755
index 0000000..3ae5db7
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/VerticalAlign.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for the <code>verticalAlign</code> property of the TextLayoutFormat class. Specifies how 
+	 *  TextFlow elements align with their containers.  
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  @see TextLayoutFormat#verticalAlign
+	 */
+	public final class VerticalAlign
+	{
+		/** Specifies alignment with the top edge of the frame. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const TOP:String = "top";
+		
+		/** Specifies alignment with the bottom edge of the frame. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const BOTTOM:String = "bottom";
+		
+		/** Specifies alignment with the middle of the frame. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		 
+		public static const MIDDLE:String = "middle";
+		
+		/** Specifies vertical line justification within the frame 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		
+		public static const JUSTIFY:String = "justify";		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/formats/WhiteSpaceCollapse.as b/textLayout_core/src/flashx/textLayout/formats/WhiteSpaceCollapse.as
new file mode 100755
index 0000000..b8aa39a
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/formats/WhiteSpaceCollapse.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.formats
+{
+	/**
+	 *  Defines values for setting the <code>whiteSpaceCollapse</code> property
+	 *  of the <code>TextLayoutFormat</code> class. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 *  
+	 *  @see TextLayoutFormat#whiteSpaceCollapse
+	 */
+	public final class WhiteSpaceCollapse
+	{
+		/** 
+		 * Collapse whitespace when importing text (default).
+		 * Within a block of imported text, removes newlines, tabs, and leading and trailing
+		 * spaces. Retains line break tags (br/) and Unicode line
+		 * separator characters.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static const COLLAPSE:String = "collapse";
+		
+		/** Preserves whitespace when importing text. 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+		*/ 
+		public static const PRESERVE:String = "preserve";
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/ArrayProperty.as b/textLayout_core/src/flashx/textLayout/property/ArrayProperty.as
new file mode 100755
index 0000000..b409ed0
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/ArrayProperty.as
@@ -0,0 +1,224 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+		
+	[ExcludeClass]
+	/** A property description with an Array value.@private */
+	public class ArrayProperty extends Property
+	{
+		private var _memberType:Class;
+		
+		public function ArrayProperty(nameValue:String, defaultValue:Array, inherited:Boolean, category:String, mType:Class)
+		{ 
+			_memberType = mType;
+			CONFIG::debug { assert(_memberType.description != null,"Array member class must have description"); }
+			// can defaultValue be INHERIT?
+			CONFIG::debug { assert(checkArrayTypes(defaultValue),"Array has bad defaultValue"); }
+			super(nameValue, defaultValue, inherited, category); 
+		}
+		
+		/** The type the members of the array are required to be. */
+		public function get memberType():Class
+		{ return _memberType; }
+		
+		protected function checkArrayTypes(val:Object):Boolean
+		{
+			if (val == null)
+				return true;
+			if (!(val is Array))
+				return false;
+			if (_memberType == null)
+				return true;
+			for each (var obj:Object in (val as Array))
+			{
+				if (!(obj is _memberType))
+					return false
+			}
+			return true;
+		}
+		
+		/** @private */
+		public override function get defaultValue():Object
+		{ return super.defaultValue == null ? null : (super.defaultValue as Array).slice();	}
+				
+		/** @private */
+		public override function setHelper(currVal:*,newVal:*):*
+		{
+			if (newVal === null)
+				newVal = undefined;
+			
+			if (newVal == undefined || newVal == FormatValue.INHERIT)
+				return newVal;
+
+			if (newVal is String)
+				newVal = this.valueFromString(String(newVal));
+			
+			if (!checkArrayTypes(newVal))
+			{
+				Property.errorHandler(this,newVal);
+				return currVal;
+			}
+			return (newVal as Array).slice(); 
+		}
+
+		/** @private */
+		public override function concatInheritOnlyHelper(currVal:*,concatVal:*):*
+		{
+			return (inherited && currVal === undefined) || currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
+
+		}	
+		/** @private */
+		public override function concatHelper(currVal:*,concatVal:*):*
+		{
+			if (inherited)
+				return currVal === undefined || currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
+			if (currVal === undefined)
+				return defaultValue;
+			return currVal == FormatValue.INHERIT ? ((concatVal is Array) ? (concatVal as Array).slice() : concatVal) : currVal;
+
+		}	
+		/** @private */
+		public override function equalHelper(v1:*,v2:*):Boolean
+		{
+			if (_memberType != null)
+			{			
+				var v1Array:Array = v1 as Array;
+				var v2Array:Array = v2 as Array;
+		
+				if (v1Array && v2Array)
+				{			
+					if (v1Array.length == v2Array.length)
+					{
+						var desc:Object = _memberType.description;
+						for (var i:int=0; i < v1Array.length; ++i)
+						{
+							if (!Property.equalAllHelper(desc, v1[i], v2[i]))
+								return false;
+						}
+						return true;
+					}
+				}
+			}
+			return v1 == v2;				
+		}
+		
+		/** @private */
+		public override function toXMLString(val:Object):String
+		{
+			if (val == FormatValue.INHERIT)
+				return String(val);
+			// TODO-7/7/2008-The XML format for array properties (as implemented below)
+			// is appropriate for what it is currently used, but can be ambiguous.
+			// For example, what if XML representations of contained elements contain the delimiters used here? 
+			 
+			// TODO: Check for description?
+			var desc:Object = _memberType.description;
+			var rslt:String = "";
+			var addSemi:Boolean = false;
+			for each (var member:Object in val)
+			{
+				if (addSemi)
+					rslt += "; "
+				// export each element ',' separated
+				var addComma:Boolean = false;
+				for each (var prop:Property in desc)
+				{
+					var val:Object = member[prop.name];
+					if (val != null)
+					{
+						if (addComma)
+							rslt += ", ";
+						rslt += prop.name + ":" + prop.toXMLString(val);
+						addComma = true;
+					}
+				}
+				addSemi = true;
+			}
+			return rslt;
+		}
+		
+		/** @private */
+		private function valueFromString(str:String):*
+		{ 	
+			// TODO-7/7/2008-The XML format for array properties can be ambiguous.
+			// See comment in toXMLString.
+			if ((str == null) || (str == "")) 
+				return null;
+			if (str == FormatValue.INHERIT)
+				return str;
+			var result:Array = new Array();
+			var desc:Object = _memberType.description;
+			
+			var attrsAll:Array = str.split('; '); 
+			for each (var attrs:String in attrsAll)
+			{
+			 	var obj:Object = new _memberType();
+			 	
+			 	var attrsOne:Array = attrs.split(', ');
+			 	for each (var attr:String in attrsOne)
+			 	{
+			 		var nameValArr:Array = attr.split(':');
+			 		var propName:String = nameValArr[0];
+			 		var propVal:String = nameValArr[1];
+			 	
+				 	for each (var prop:Property in desc)
+				 	{
+				 		if (prop.name == propName)
+				 		{
+				 			obj[propName] = prop.setHelper(propVal,obj[propName]);
+				 			break;
+				 		}
+			 		}
+			 	}
+			 	result.push(obj);
+			}
+				
+			return result; 
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			CONFIG::debug { assert(!(val is String),"ArrayProperty.has non inherit string"); }
+				
+			var hash:uint = seed;
+			
+			// TODO: Check for description?
+			var desc:Object = _memberType.description;
+			for each (var member:Object in val)
+			{
+				for each (var prop:Property in desc)
+				{
+					var val:Object = member[prop.name];
+					if (val != null)
+						hash = prop.hash(val, hash);
+				}
+			}
+			return hash;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/BooleanProperty.as b/textLayout_core/src/flashx/textLayout/property/BooleanProperty.as
new file mode 100755
index 0000000..f72e8fe
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/BooleanProperty.as
@@ -0,0 +1,61 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+		
+	[ExcludeClass]
+	/** A property description with a Boolean value. @private */
+	public class BooleanProperty extends Property
+	{
+		public function BooleanProperty(nameValue:String, defaultValue:Boolean, inherited:Boolean, category:String)
+		{
+			super(nameValue, defaultValue, inherited, category);
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+
+			if (newObject === undefined || newObject is Boolean || newObject == FormatValue.INHERIT)
+				return newObject;
+			
+			if (newObject == "true" || newObject == "false")
+				return newObject == "true";
+			
+			Property.errorHandler(this,newObject);
+			return currVal;	
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			CONFIG::debug { assert(!(val is String),"BooleanProperty.has non inherit string"); }
+			return UintProperty.doHash((val as Boolean) ? 1 : 0, seed);
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/EnumStringProperty.as b/textLayout_core/src/flashx/textLayout/property/EnumStringProperty.as
new file mode 100755
index 0000000..06474a1
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/EnumStringProperty.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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+		
+	[ExcludeClass]
+	/** An property description with an enumerated string as its value. @private */
+	public class EnumStringProperty extends Property
+	{
+		private var _range:Object;
+		
+		public function EnumStringProperty(nameValue:String, defaultValue:String, inherited:Boolean, category:String, ... rest)
+		{ 
+			super(nameValue, defaultValue, inherited, category);
+			_range = createRange(rest); 
+		}
+		
+		/** @private */
+		tlf_internal static var nextEnumHashValue:uint = 217287;
+		
+		/** @private */
+		tlf_internal static function createRange(rest:Array):Object
+		{
+			var range:Object = new Object();
+			// rest is the list of possible values
+			for (var i:int = 0; i < rest.length; i++)
+				range[rest[i]] = nextEnumHashValue++;
+			range[FormatValue.INHERIT] = nextEnumHashValue++;	
+			return range;
+		}
+		
+		/** Returns object whose properties are the legal enum values */
+		public function get range():Object
+		{
+			return Property.shallowCopy(_range); 
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined)
+				return newObject;
+				
+			if (_range.hasOwnProperty(newObject))
+				return newObject;
+			Property.errorHandler(this,newObject);
+			return currVal;
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			CONFIG::debug { assert(_range.hasOwnProperty(val), "String " + val + " not among possible values for this EnumStringProperty"); }
+			return UintProperty.doHash(_range[val], seed);
+		}
+		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/IntProperty.as b/textLayout_core/src/flashx/textLayout/property/IntProperty.as
new file mode 100755
index 0000000..6a88a65
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/IntProperty.as
@@ -0,0 +1,84 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** A property description with an integer value. @private */
+	public class IntProperty extends Property
+	{
+		private var _minValue:int;
+		private var _maxValue:int;
+		
+		public function IntProperty(nameValue:String, defaultValue:int, inherited:Boolean, category:String, minValue:int, maxValue:int)
+		{
+			super(nameValue, defaultValue, inherited, category);
+			_minValue = minValue;
+			_maxValue = maxValue;
+		}
+		
+		public function get minValue():int
+		{ return _minValue; }
+		public function get maxValue():int
+		{ return _maxValue; } 
+
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined || newObject == FormatValue.INHERIT)
+				return newObject;
+
+			var newValNumber:Number = parseInt(newObject);
+			if (isNaN(newValNumber))
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			var newVal:int = int(newValNumber);
+			if (checkLowerLimit() && newVal < _minValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			if (checkUpperLimit() && newVal > _maxValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			return newVal;
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			CONFIG::debug { assert(!(val is String),"IntProperty.has non inherit string"); }
+			return UintProperty.doHash(val as uint, seed);
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/IntWithEnumProperty.as b/textLayout_core/src/flashx/textLayout/property/IntWithEnumProperty.as
new file mode 100755
index 0000000..6204254
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/IntWithEnumProperty.as
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+			
+	[ExcludeClass]
+	/** A property description with an integer or enumerated string as its value. @private */
+	public class IntWithEnumProperty extends IntProperty
+	{
+		private var _range:Object;
+		private var _defaultValue:Object;		// could be Int or EnumString value
+		
+		public function IntWithEnumProperty(nameValue:String, defaultValue:Object, inherited:Boolean, category:String, minValue:int, maxValue:int, ... rest)
+		{
+			// rest is the list of possible values
+			_range = EnumStringProperty.createRange(rest); 
+				
+			var defaultIsEnum:Boolean = defaultValue is String && _range.hasOwnProperty(defaultValue);
+			var numberDefault:int = defaultIsEnum ? 0 : int(defaultValue);
+			super(nameValue, numberDefault, inherited, category, minValue, maxValue);
+			_defaultValue = defaultValue;
+		}
+		
+		/** @private */
+		public override function get defaultValue():Object
+		{ return _defaultValue; }
+		
+		/** Returns object whose properties are the legal enum values */
+		public function get range():Object
+		{
+			return Property.shallowCopy(_range); 
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined)	// range has INHERIT
+				return newObject;
+				
+			return _range.hasOwnProperty(newObject) ? newObject : super.setHelper(currVal,newObject);
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			CONFIG::debug { assert(!(val is String) || _range.hasOwnProperty(val), "String " + val + " not among possible values for this IntWithEnumProperty"); }
+			var hash:uint = _range[val];
+			if (hash != 0)
+				return UintProperty.doHash(hash, seed);
+			return super.hash(val, seed);
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/NumberOrPercentOrEnumProperty.as b/textLayout_core/src/flashx/textLayout/property/NumberOrPercentOrEnumProperty.as
new file mode 100755
index 0000000..d35071a
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/NumberOrPercentOrEnumProperty.as
@@ -0,0 +1,78 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** A property description with a Number or a Percent or enumerated string as its value. @private */
+	public class NumberOrPercentOrEnumProperty extends NumberOrPercentProperty
+	{
+		private var _range:Object;
+		private var _defaultValue:Object;		// could be Number or Percent or EnumString value
+
+		/** Value will be a % terminated string or a number or an enumeration */
+		public function NumberOrPercentOrEnumProperty(nameValue:String, defaultValue:Object, inherited:Boolean, category:String, minValue:Number, maxValue:Number, minPercentValue:String, maxPercentValue:String, ... rest)
+		{
+			// rest is the list of possible values
+			_range = EnumStringProperty.createRange(rest); 
+
+			if (defaultValue is String && _range.hasOwnProperty(defaultValue))
+				_defaultValue = defaultValue;
+			// leave _defaultValue null if its not an enum
+
+			super(nameValue, defaultValue, inherited, category, minValue, maxValue, minPercentValue, maxPercentValue);
+		}
+		
+		/** @private */
+		public override function get defaultValue():Object
+		{ return (_defaultValue != null) ? _defaultValue : super.defaultValue; }
+		
+		/** Returns object whose properties are the legal enum values */
+		public function get range():Object
+		{
+			return Property.shallowCopy(_range); 
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined)	// range has INHERIT
+				return newObject;
+				
+			return _range.hasOwnProperty(newObject) ? newObject : super.setHelper(currVal,newObject);
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			var hash:uint = _range[val];
+			if (hash != 0)
+				return UintProperty.doHash(hash, seed);
+			return super.hash(val, seed);
+		}		
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/NumberOrPercentProperty.as b/textLayout_core/src/flashx/textLayout/property/NumberOrPercentProperty.as
new file mode 100755
index 0000000..8b0e237
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/NumberOrPercentProperty.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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** A property description with a Number or a Percent as its value. @private */
+	public class NumberOrPercentProperty extends Property
+	{
+		private var _minNumberValue:Number;
+		private var _maxNumberValue:Number;
+		private var _minPercentValue:Number;
+		private var _maxPercentValue:Number;
+		
+		/** Value will be a % terminated string or a number */
+		public function NumberOrPercentProperty(nameValue:String, defaultValue:Object, inherited:Boolean, category:String, minValue:Number, maxValue:Number, minPercentValue:String, maxPercentValue:String)
+		{
+			super(nameValue, defaultValue, inherited, category);
+			
+			// the nested properties don't need the true default
+			_minNumberValue = minValue;
+			_maxNumberValue = maxValue;
+			_minPercentValue = toNumberIfPercent(minPercentValue);
+			_maxPercentValue = toNumberIfPercent(maxPercentValue);
+		}
+		
+		public function get minNumberValue():Number
+		{ return _minNumberValue; }
+		public function get maxNumberValue():Number
+		{ return _maxNumberValue; } 
+		public function get minPercentValue():Number
+		{ return _minPercentValue; }
+		public function get maxPercentValue():Number
+		{ return _maxPercentValue; }
+		
+		static private function toNumberIfPercent(o:Object):Number
+		{
+			if (!(o is String))
+				return NaN;
+			var s:String = String(o);
+			var len:int = s.length;
+			
+			return len != 0 && s.charAt(len-1) == "%" ? parseFloat(s) : NaN;
+		}
+
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined || newObject == FormatValue.INHERIT)
+				return newObject;
+
+			var newVal:Number = toNumberIfPercent(newObject);
+			if (!isNaN(newVal))
+			{
+				if (checkLowerLimit() && newVal < _minPercentValue)
+				{
+					Property.errorHandler(this,newObject);
+					return currVal;
+				}
+				if (checkUpperLimit() && newVal > _maxPercentValue)
+				{
+					Property.errorHandler(this,newObject);
+					return currVal;
+				}
+				return newVal.toString()+"%";
+			}
+
+			newVal = parseFloat(newObject);
+			// Nan --> return the current value
+			if (isNaN(newVal))
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			if (checkLowerLimit() && newVal < _minNumberValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			if (checkUpperLimit() && newVal > _maxNumberValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			return newVal;
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			if (val is String)
+				return StringProperty.doHash(String(val), seed);
+			return NumberProperty.doHash(val as Number, seed);
+		}
+		
+		public function computeActualPropertyValue(propertyValue:Object,percentInput:Number):Number
+		{
+			var percent:Number = toNumberIfPercent(propertyValue);
+			if (isNaN(percent))
+				return Number(propertyValue);
+				
+			// its a percent - calculate and clamp
+			var rslt:Number =  percentInput * (percent / 100);
+			if (rslt < _minNumberValue)
+				return _minNumberValue;
+			if (rslt > _maxNumberValue)
+				return _maxNumberValue;
+			return rslt;			
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/NumberProperty.as b/textLayout_core/src/flashx/textLayout/property/NumberProperty.as
new file mode 100755
index 0000000..f7ddd23
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/NumberProperty.as
@@ -0,0 +1,98 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** A property description with a Number as its value. @private */
+	public class NumberProperty extends Property
+	{
+		private var _minValue:Number;
+		private var _maxValue:Number;
+		
+		public function NumberProperty(nameValue:String, defaultValue:Number, inherited:Boolean, category:String, minValue:Number, maxValue:Number)
+		{
+			super(nameValue, defaultValue, inherited, category);
+			_minValue = minValue;
+			_maxValue = maxValue;
+		}
+		
+		public function get minValue():Number
+		{ return _minValue; }
+		public function get maxValue():Number
+		{ return _maxValue; } 
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined || newObject == FormatValue.INHERIT)
+				return newObject;
+
+			var newVal:Number = newObject is String ? parseFloat(newObject) : Number(newObject);
+			if (isNaN(newVal))
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			if (checkLowerLimit() && newVal < _minValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			if (checkUpperLimit() && newVal > _maxValue)
+			{
+				Property.errorHandler(this,newObject);
+				return currVal;
+			}
+			return newVal;
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			return NumberProperty.doHash(val as Number, seed);
+		}
+		
+		/** @private */
+		tlf_internal static function doHash(num:Number, seed:uint):uint
+		{ 
+			//return stringHash(num.toString(), seed);
+			
+			var trunc:uint = uint(num);
+			var hash:uint = UintProperty.doHash(trunc, seed);
+			if (trunc != num)
+			{
+				var fraction:uint = (uint)((num - trunc) * 10000000000);
+				hash =  UintProperty.doHash(fraction, hash);
+			}
+			
+			return hash; 
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/NumberWithEnumProperty.as b/textLayout_core/src/flashx/textLayout/property/NumberWithEnumProperty.as
new file mode 100755
index 0000000..420ce07
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/NumberWithEnumProperty.as
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+			
+	[ExcludeClass]
+	/** A property description with a Number or enumerated string as its value. @private */
+	public class NumberWithEnumProperty extends NumberProperty
+	{
+		private var _range:Object;
+		private var _defaultValue:Object;		// could be Number or EnumString value
+		
+		public function NumberWithEnumProperty(nameValue:String, defaultValue:Object, inherited:Boolean, category:String, minValue:Number, maxValue:Number, ... rest)
+		{
+			// rest is the list of possible values
+			_range = EnumStringProperty.createRange(rest); 
+				
+			var defaultIsEnum:Boolean = defaultValue is String && _range.hasOwnProperty(defaultValue);
+			var numberDefault:Number = defaultIsEnum ? 0 : Number(defaultValue);
+			super(nameValue, numberDefault, inherited, category, minValue, maxValue);
+			_defaultValue = defaultValue;
+		}
+		
+		/** @private */
+		public override function get defaultValue():Object
+		{ return _defaultValue; }
+		
+		/** Returns object whose properties are the legal enum values */
+		public function get range():Object
+		{
+			return Property.shallowCopy(_range); 
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined)	// range has INHERIT
+				return newObject;
+				
+			return _range.hasOwnProperty(newObject) ? newObject : super.setHelper(currVal,newObject);
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			CONFIG::debug { assert(!(val is String) || _range.hasOwnProperty(val), "String " + val + " not among possible values for this NumberWithEnumProperty"); }
+			var hash:uint = _range[val];
+			if (hash != 0)
+				return UintProperty.doHash(hash, seed);
+			return super.hash(val, seed);
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/property/Property.as b/textLayout_core/src/flashx/textLayout/property/Property.as
new file mode 100755
index 0000000..4ea425e
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/Property.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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	[ExcludeClass]
+	/** Base class of property metadata.  Each property in the various TextLayout attributes structures has a metadata singletion Property class instance.  The instance
+	 * can be used to process the property to and from xml, find out range information and help with the attribute cascade.  The Property class also contains static functions
+	 * for processing all the properties collected in a TextLayout Format object. @private  */
+	public class Property
+	{
+		public static var errorHandler:Function = defaultErrorHandler;
+		public static function defaultErrorHandler(p:Property,value:Object):void
+		{
+			throw(new RangeError(createErrorString(p,value)));
+		}
+		public static function createErrorString(p:Property,value:Object):String
+		{
+			return GlobalSettings.resourceStringFunction("badPropertyValue",[ p.name, value.toString() ])
+		}
+		
+		/** not yet enabled.  @private */
+		public const NO_LIMITS:String ="noLimits";
+		/** not yet enabled.  @private */
+		public const LOWER_LIMIT:String ="lowerLimit";
+		/** not yet enabled.  @private */
+		public const UPPER_LIMIT:String = "upperLimit";
+		/** not yet enabled.  @private */
+		public const ALL_LIMITS:String = "allLimits";
+		
+		// storing name here is redundant but is more efficient 
+		private var _name:String;
+		private var _default:Object;
+		private var _inherited:Boolean;
+		private var _limits:String;
+		private var _category:String;
+		
+		/** @private */
+		tlf_internal static const inheritHashValue:uint  = 314159;
+		
+		/** Initializer.  Each property has a name and a default. */
+		public function Property(nameValue:String,defaultValue:Object,inherited:Boolean,category:String)
+		{
+			_name = nameValue;
+			_default = defaultValue;
+			_limits = ALL_LIMITS;
+			_inherited = inherited;
+			_category = category;
+		}
+		
+		/** not yet enabled.  @private */
+		protected function checkLowerLimit():Boolean
+		{ return _limits == ALL_LIMITS || _limits == LOWER_LIMIT; }
+		
+		/** not yet enabled.  @private */
+		protected function checkUpperLimit():Boolean
+		{ return _limits == ALL_LIMITS || _limits == LOWER_LIMIT; }
+		
+		/** The name of the property */
+		public function get name():String
+		{ return _name; }
+		
+		/** The default value of this property */
+		public function get defaultValue():Object
+		{ return _default; }
+		
+		/** Is this property inherited */
+		public function get inherited():Object
+		{ return _inherited; }
+		
+		/** Category of this property. */
+		public function get category():String
+		{ return _category; }
+			
+		/** Helper function when setting the property */
+		public function setHelper(currVal:*,newVal:*):*
+		{
+			if (newVal === null)
+				newVal = undefined;
+
+			return newVal; 
+		}
+		
+		/** Helper function when merging the property to compute actual attributes */
+		public function concatInheritOnlyHelper(currVal:*,concatVal:*):*
+		{
+			return (_inherited && currVal === undefined) || currVal == FormatValue.INHERIT ? concatVal : currVal;
+		}
+		/** Helper function when merging the property to compute actual attributes */
+		public function concatHelper(currVal:*,concatVal:*):*
+		{
+			if (_inherited)
+				return currVal === undefined || currVal == FormatValue.INHERIT ? concatVal : currVal;
+			if (currVal === undefined)
+				return defaultValue;
+			return currVal == FormatValue.INHERIT ? concatVal : currVal;
+		}
+		
+		/** Helper function when comparing the property */
+		public function equalHelper(v1:*,v2:*):Boolean
+		{ return v1 == v2; }
+		
+		/** Convert the value of this property to a string appropriate for XML export */
+		public function toXMLString(val:Object):String
+		{
+			return val.toString();
+		}
+		
+		/** Get the hash of the property value
+		 * @param val the property value
+		 * @param seed seed value for the hash algorithm 
+		 * @return the hash of the property value
+		 */
+		public function hash(val:Object, seed:uint):uint
+		{ 
+			return 0;
+		}
+		
+		// /////////////////////////////////////////////
+		// Following static functions are used by Format classes to 
+		// perform functions that iterate over all the attributes.
+		// They are driven by the attributes metadata object that contains
+		// definitions for all the properties.
+		// /////////////////////////////////////////////
+			
+		/** Helper function to initialize all property values from defaults. */
+		static public function defaultsAllHelper(description:Object,current:Object):void
+		{
+			for each (var prop:Property in description)
+				current[prop.name] = prop.defaultValue;
+		}
+		
+		/** Helper function to compare two sets of properties. */
+		static public function equalAllHelper(description:Object,p1:Object,p2:Object):Boolean
+		{
+			if (p1 == p2)
+				return true;
+			// these could be "equal" if all attributes of p1 or p2 are null
+			if (p1 == null || p2 == null)
+				return false;
+			for each (var prop:Property in description)
+			{
+				var name:String = prop.name;
+				if (!(prop.equalHelper(p1[name],p2[name])))
+					return false;
+			}
+			return true;
+		}
+
+		static public function extractInCategory(formatClass:Class,description:Object,props:Object,category:String):Object
+		{
+			var rslt:Object = null;
+			for each (var prop:Property in description)
+			{
+				if (prop.category == category && props[prop.name] != null)
+				{
+					if (rslt == null)
+						rslt = new formatClass();
+					rslt[prop.name] = props[prop.name];
+				}
+			}
+			return rslt;
+		}
+		/** @private */
+		static public function shallowCopy(src:Object):Object
+		{
+			// make a shallow copy
+			var rslt:Object = new Object()
+			for (var val:Object in src)
+				rslt[val] = src[val]; 
+			return rslt;
+		}
+		
+		static private const nullStyleObject:Object = new Object();
+		/** @private */
+		static public function equalStyleObjects(o1:Object,o2:Object):Boolean
+		{
+			if (o1 == null)
+				o1 = nullStyleObject;
+			if (o2 == null)
+				o2 = nullStyleObject;
+			var o1len:int = 0;
+			// compare property values and count o1len
+			for (var val:Object in o1)
+			{
+				CONFIG::debug { assert(!(o1[val] is Array) && !(o2[val] is Array),"Arrays as user styles not supported"); }
+				if (o1[val] != o2[val])
+					return false;	// different
+				o1len++;
+			}
+			var o2len:int = 0;
+			for (val in o2)
+				o2len++;
+			// matching keys from o1 to o2.  return equal if they both have the same length
+			return o1len == o2len;
+		}
+		
+		/** @private */
+		static public function equalCoreStyles(o1:Object,o2:Object,description:Object):Boolean
+		{
+			if (o1 == null)
+				o1 = nullStyleObject;
+			if (o2 == null)
+				o2 = nullStyleObject;
+			var o1len:int = 0;
+			// compare property values and count o1len
+			for (var val:String in o1)
+			{
+				var o1val:Object = o1[val];
+				var o2val:Object = o2[val];
+				if (o1val != o2val)
+				{
+					if (!(o1val is Array) || !(o2val is Array) || o1val.length != o2val.length)
+						return false;	// different
+					var valClass:Class = description[val].memberType;
+					if (!Property.equalAllHelper(valClass.tlf_internal::description,o1val,o2val))
+						return false;
+				}
+				o1len++;
+			}
+			var o2len:int = 0;
+			for (val in o2)
+				o2len++;
+			// matching keys from o1 to o2.  return equal if they both have the same length
+			return o1len == o2len;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/StringProperty.as b/textLayout_core/src/flashx/textLayout/property/StringProperty.as
new file mode 100755
index 0000000..7972203
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/StringProperty.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 flashx.textLayout.property
+{
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/** A property description with a String as its value @private */
+	public class StringProperty extends Property
+	{
+		public function StringProperty(nameValue:String, defaultValue:String, inherited:Boolean, category:String)
+		{
+			super(nameValue, defaultValue, inherited, category);
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined || newObject is String)
+				return newObject;
+			
+			Property.errorHandler(this,newObject);
+			return currVal;	
+		}	
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			return doHash(val as String, seed);
+		}
+		
+		/** @private */
+		tlf_internal static function doHash(val:String, seed:uint):uint
+		{
+			if (val == null)
+				return seed;
+				
+			var len:uint = val.length;
+			var hash:uint = seed;
+
+			// Incrementally hash integers composed of pairs of character codes in the string
+			for (var ix:uint=0; ix<len/2; ix++)
+			{
+				hash = UintProperty.doHash((val.charCodeAt(2*ix) << 16) | val.charCodeAt(2*ix+1), hash);
+			}
+			
+			// Handle last character code in an odd-length string
+			if (len % 2 != 0)
+				hash = UintProperty.doHash (val.charCodeAt(len-1), hash);
+			
+			return hash;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/TabStopsProperty.as b/textLayout_core/src/flashx/textLayout/property/TabStopsProperty.as
new file mode 100755
index 0000000..9bacf2c
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/TabStopsProperty.as
@@ -0,0 +1,194 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flash.text.engine.TabAlignment;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.TabStopFormat;
+		
+	[ExcludeClass]
+	/** Property for tab stops. Extends ArrayProperty; setter takes a string representation of tab stops in addition to an array. @private */
+	public class TabStopsProperty extends ArrayProperty
+	{
+		public function TabStopsProperty(nameValue:String, defaultValue:Array, inherited:Boolean, category:String)
+		{ 
+			super (nameValue, defaultValue, inherited, category, TabStopFormat);
+		}
+			
+		
+		/** Helper function when setting the property */
+		public override function setHelper(currVal:*,newVal:*):*
+		{
+			// null is a real value - DO NOT map to undefined like the others
+			
+			// null, undefined and INHERIT are all valid for arrays
+			if (newVal == null || newVal == FormatValue.INHERIT)
+				return newVal;
+				
+			// Accepts either an array or a string representation
+			var tabStops:Array = newVal as Array;
+			if (tabStops)
+			{
+				if (!checkArrayTypes(tabStops))
+				{
+					Property.errorHandler(this,newVal);
+					return currVal;
+				}
+			}
+			else
+			{
+				var valString:String = newVal as String;
+				if (!valString)
+				{
+					Property.errorHandler(this,newVal);
+					return currVal;
+				}
+					
+				// Parse the string representation and create an equivalent array
+				tabStops = new Array();
+				
+				// Replace escape sequences (\ followed by a space or \) with placeholder strings
+				// that can't naturally occur in the passed-in string 
+				valString = valString.replace(_escapeBackslashRegex, _backslashPlaceHolder);
+				valString = valString.replace(_escapeSpaceRegex, _spacePlaceHolder);
+				
+				_tabStopRegex.lastIndex = 0;
+				do
+				{
+					var result:Object = _tabStopRegex.exec(valString);
+					if (!result)
+						break; // no more matches
+						
+					var tabStop:TabStopFormat = new TabStopFormat();
+					switch (result[1].toLowerCase())
+					{
+						case "s":
+						case "": // START is the default
+							tabStop.alignment = TabAlignment.START;
+							break;
+						case "c":
+							tabStop.alignment = TabAlignment.CENTER;
+							break;
+						case "e":
+							tabStop.alignment = TabAlignment.END;
+							break;
+						case "d":
+							tabStop.alignment = TabAlignment.DECIMAL;
+							break;
+					}
+					
+					var position:Number = Number(result[2]); 
+					if (isNaN(position))
+					{
+						Property.errorHandler(this,newVal);
+						return currVal;
+					}
+					tabStop.position = position;
+
+					if (tabStop.alignment == TabAlignment.DECIMAL)
+					{
+						if (result[3] == "")
+							tabStop.decimalAlignmentToken = "."; //default
+						else
+						{
+							// strip the leading vertical bar and restore \ and space characters where intended
+							tabStop.decimalAlignmentToken = result[3].slice(1).replace(_backslashPlaceholderRegex, "\\");
+							tabStop.decimalAlignmentToken = tabStop.decimalAlignmentToken.replace(_spacePlaceholderRegex, " ");
+						}
+					}
+					else if (result[3] != "")
+					{
+						Property.errorHandler(this,newVal);
+						return currVal; // if alignment is not decimal, the alignment token is not allowed
+					}
+						
+					tabStops.push(tabStop);
+				
+				} while (true);
+			
+			}
+
+			return tabStops.sort(compareTabStopFormats);
+		}
+		
+		/** @private */
+		public override function toXMLString(val:Object):String
+		{
+			var str:String = "";
+			var tabStops:Array = val as Array;
+			for each (var tabStop:TabStopFormat in tabStops)
+			{
+				if (str.length)
+					str += " ";
+				
+				switch (tabStop.alignment)
+				{
+					case TabAlignment.START:
+						str += "s";
+						break;
+					case TabAlignment.CENTER:
+						str += "c";
+						break;
+					case TabAlignment.END:
+						str += "e";
+						break;
+					case TabAlignment.DECIMAL:
+						str += "d";
+						break;
+				}
+				
+				str += tabStop.position.toString();
+				
+				if (tabStop.alignment == TabAlignment.DECIMAL)
+				{
+					var escapedAlignmentToken:String = tabStop.decimalAlignmentToken.replace(_backslashRegex, "\\\\");
+					escapedAlignmentToken = escapedAlignmentToken.replace(_spaceRegex, "\\ ");
+					str += "|" + escapedAlignmentToken;
+				}
+			}
+			
+			return str;
+		}
+		
+		private static function compareTabStopFormats(a:TabStopFormat, b:TabStopFormat):Number
+		{
+			return a.position == b.position ? 0 : a.position < b.position ? -1 : 1;
+		}
+		
+		// Alignment type: [sScCeEdD]?  - Atmost 1 occurance of one of s/c/e/d (or upper-case equivalents)
+		// Position: [^| ]+ - At least character which is not a space or | (further validation is done by the Number constructor)
+		// Alignment token and separator:(|[^ ]*)? - Atmost one occurance of a | followed by 0 or more non-space characters
+		// Delimiter: ( |$) - A space or end-of-string
+		private static const _tabStopRegex:RegExp = /([sScCeEdD]?)([^| ]+)(|[^ ]*)?( |$)/g;
+		private static const _escapeBackslashRegex:RegExp = /\\\\/g;
+		private static const _escapeSpaceRegex:RegExp = /\\ /g;
+		private static const _backslashRegex:RegExp = /\\/g;
+		private static const _spaceRegex:RegExp = / /g;
+		private static const _backslashPlaceholderRegex:RegExp = /\uE000/g;
+		private static const _spacePlaceholderRegex:RegExp = /\uE001/g;
+		
+		// Replace escape sequences (\ followed by a space or \) with placeholder strings
+		// containing characters from Unicode private use area (won't naturally occur in the passed-in string) 
+		private static const _backslashPlaceHolder:String = String.fromCharCode(0xE000);
+		private static const _spacePlaceHolder:String = String.fromCharCode(0xE001);
+				
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/UintProperty.as b/textLayout_core/src/flashx/textLayout/property/UintProperty.as
new file mode 100755
index 0000000..9111bc5
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/UintProperty.as
@@ -0,0 +1,106 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/** A property description with an unsigned integer as its value.  Typically used for color. @private */
+	public class UintProperty extends Property
+	{
+		public function UintProperty(nameValue:String, defaultValue:uint, inherited:Boolean, category:String)
+		{
+			super(nameValue, defaultValue, inherited, category);
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined || newObject == FormatValue.INHERIT)
+				return newObject;
+			
+			var newVal:*;
+			if (newObject is String)
+			{
+				var str:String = String(newObject);
+				// Normally, we could just cast a string to a uint. However, the casting technique only works for
+				// normal numbers and numbers preceded by "0x". We can encounter numbers of the form "#ffffffff"					
+				if (str.substr(0, 1) == "#")
+					str = "0x" + str.substr(1, str.length-1);
+				newVal = (str.toLowerCase().substr(0, 2) == "0x") ? parseInt(str) : NaN;
+			}
+			else if (newObject is Number || newObject is int || newObject is uint)
+				newVal = Number(newObject);
+			else
+				newVal = NaN;
+			
+			if (isNaN(newVal))
+			{
+				Property.errorHandler(this,str);
+				return currVal;
+			}
+			
+			if (newVal is Number)
+			{
+				if (newVal < 0 || newVal > 0xffffffff)
+				{
+					Property.errorHandler(this,newObject);
+					return currVal;					
+				}
+			}
+			
+			return newVal;
+		}
+		
+		/** @private */
+		public override function toXMLString(val:Object):String
+		{
+			// Always export in # format, to be compatible with color spec.
+			if (val == FormatValue.INHERIT)
+				return String(val);
+				
+			var result:String = val.toString(16);
+			if (result.length < 6)
+				result = "000000".substr(0, 6 - result.length) + result;
+			result = "#" + result;
+			return result;
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			if (val == FormatValue.INHERIT)
+				return UintProperty.doHash(inheritHashValue, seed);
+			return doHash(val as uint, seed);
+		}
+		
+		/** @private */
+		tlf_internal static function doHash(val:uint, seed:uint):uint
+		{ 
+			return ((seed << 5) ^ (seed >> 27)) ^ val;
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/property/UintWithEnumProperty.as b/textLayout_core/src/flashx/textLayout/property/UintWithEnumProperty.as
new file mode 100755
index 0000000..81d3bfd
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/property/UintWithEnumProperty.as
@@ -0,0 +1,83 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.property
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+			
+	[ExcludeClass]
+	/** A property description with a Uint or enumerated string as its value. @private */
+	public class UintWithEnumProperty extends UintProperty
+	{
+		private var _range:Object;
+		private var _defaultValue:Object;		// could be Uint or EnumString value
+		
+		public function UintWithEnumProperty(nameValue:String, defaultValue:Object, inherited:Boolean, category:String,  ... rest)
+		{
+			// rest is the list of possible values
+			_range = EnumStringProperty.createRange(rest); 
+				
+			var defaultIsEnum:Boolean = defaultValue is String && _range.hasOwnProperty(defaultValue);
+			var numberDefault:Number = defaultIsEnum ? 0 : Number(defaultValue);
+			super(nameValue, numberDefault, inherited, category);
+			_defaultValue = defaultValue;
+		}
+		
+		/** @private */
+		public override function get defaultValue():Object
+		{ return _defaultValue; }
+		
+		/** Returns object whose properties are the legal enum values */
+		public function get range():Object
+		{
+			return Property.shallowCopy(_range); 
+		}
+		
+		/** @private */
+		public override function setHelper(currVal:*,newObject:*):*
+		{ 
+			if (newObject === null)
+				newObject = undefined;
+			
+			if (newObject === undefined)	// range has INHERIT
+				return newObject;
+				
+			return _range.hasOwnProperty(newObject) ? newObject : super.setHelper(currVal,newObject);
+		}
+		
+		/** @private */
+		public override function hash(val:Object, seed:uint):uint
+		{ 
+			CONFIG::debug { assert(!(val is String) || _range.hasOwnProperty(val), "String " + val + " not among possible values for this NumberWithEnumProperty"); }
+			var hash:uint = _range[val];
+			if (hash != 0)
+				return UintProperty.doHash(hash, seed);
+			return super.hash(val, seed);
+		}
+		
+		/** @private */
+		public override function toXMLString(val:Object):String
+		{
+			return _range.hasOwnProperty(val) ? String(val) : super.toXMLString(val);
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/tlf_internal.as b/textLayout_core/src/flashx/textLayout/tlf_internal.as
new file mode 100755
index 0000000..358ca67
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/tlf_internal.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 flashx.textLayout
+{
+
+	/**
+	 *  This namespace is used for undocumented APIs -- usually implementation
+	 *  details -- which can't be private because they need to visible
+	 *  to other classes.
+	 *  APIs in this namespace are completely unsupported and are likely to
+	 *  change in future versions of TextLayout.
+	 * 
+	 *  @private
+	 */
+	public namespace tlf_internal =
+		"http://ns.adobe.com/textLayout/internal/2008";
+}
+
diff --git a/textLayout_core/src/flashx/textLayout/utils/CharacterUtil.as b/textLayout_core/src/flashx/textLayout/utils/CharacterUtil.as
new file mode 100755
index 0000000..0f725d1
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/utils/CharacterUtil.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 flashx.textLayout.utils
+{
+	/** 
+	 * Utilities for managing and getting information about characters.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>CharacterUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class CharacterUtil
+	{
+		/** 
+		 * Returns <code>true</code> if the <code>charCode</code> argument is a high word in a surrogate pair. 
+		 * A surrogate pair represents a character with a code point that requires more
+		 * than sixteen bits to express and thus requires a combination
+		 * of two 16-bit words, a high surrogate and a low surrogate, to embody its code point.
+		 * <p>This method can be used when processing a series of characters to
+		 * ensure that you do not inadvertently divide a surrogate pair
+		 * into incomplete halves.</p>
+		 * 
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 * @return <code>true</code> if <code>charCode</code> is the high surrogate in a surrogate pair.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isHighSurrogate(charCode:int):Boolean
+		{
+			return (charCode >= 0xD800 && charCode <= 0xDBFF);
+		}
+		
+		/** 
+		 * Returns <code>true</code> if the <code>charCode</code> argument is a low word in a surrogate pair. 
+		 * A surrogate pair represents a character with a code point that requires more
+		 * than sixteen bits to express and thus requires a combination
+		 * of two 16-bit words, a high surrogate and a low surrogate, to embody its code point.
+		 * <p>This method can be used when processing a series of characters to
+		 * ensure that you do not inadvertently divide a surrogate pair
+		 * into incomplete halves.</p>
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 * @return <code>true</code> if <code>charCode</code> is the low surrogate in a surrogate pair.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isLowSurrogate (charCode:int):Boolean
+		{
+			return (charCode >= 0xDC00 && charCode <= 0xDFFF);
+		}
+
+		static private var whiteSpaceObject:Object = createWhiteSpaceObject();
+		
+		static private function createWhiteSpaceObject():Object
+		{
+			var rslt:Object = new Object();
+			//members of SpaceSeparator category
+			rslt[0x0020] =  true;  //SPACE
+			rslt[0x1680] =  true;  //OGHAM SPACE MARK
+			rslt[0x180E] =  true;  //MONGOLIAN VOWEL SEPARATOR
+			rslt[0x2000] =  true;  //EN QUAD
+			rslt[0x2001] =  true;  //EM QUAD
+			rslt[0x2002] =  true;  //EN SPACE
+			rslt[0x2003] =  true;  //EM SPACE
+			rslt[0x2004] =  true;  //THREE-PER-EM SPACE
+			rslt[0x2005] =  true;  //FOUR-PER-EM SPACE
+			rslt[0x2006] =  true;  //SIZE-PER-EM SPACE
+			rslt[0x2007] =  true;  //FIGURE SPACE
+			rslt[0x2008] =  true;  //PUNCTUATION SPACE
+			rslt[0x2009] =  true;  //THIN SPACE
+			rslt[0x200A] =  true;  //HAIR SPACE
+			rslt[0x202F] =  true;  //NARROW NO-BREAK SPACE
+			rslt[0x205F] =  true;  //MEDIUM MATHEMATICAL SPACE
+			rslt[0x3000] =  true;  //IDEOGRAPHIC SPACE
+			//members of LineSeparator category
+			rslt[0x2028] =  true;  //LINE SEPARATOR
+			//members of ParagraphSeparator category
+			rslt[0x2029] =  true;
+			//Other characters considered to be a space
+			rslt[0x0009] =  true; //CHARACTER TABULATION
+			rslt[0x000A] =  true; //LINE FEED
+			rslt[0x000B] =  true; //LINE TABULATION
+			rslt[0x000C] =  true; //FORM FEED
+			rslt[0x000D] =  true; //CARRIAGE RETURN
+			rslt[0x0085] =  true; //NEXT LINE
+			rslt[0x00A0] =  true; //NO-BREAK SPACE	
+			return rslt;
+		}
+		/** 
+		 * Returns <code>true</code> if <code>charCode</code> is a whitespace character. 
+		 * <p>The following table describes all characters that this
+		 * method considers a whitespace character.
+		 * </p>
+		 * <table class="innertable">
+		 *     <tr><th>Character Code</th><th>Unicode Character Name</th><th>Category</th></tr>
+		 *     <tr><td><code>0x0020</code></td><td>SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x1680</code></td><td>OGHAM SPACE MARK</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x180E</code></td><td>MONGOLIAN VOWEL SEPARATOR</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2000</code></td><td>EN QUAD</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2001</code></td><td>EM QUAD</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2002</code></td><td>EN SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2003</code></td><td>EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2004</code></td><td>THREE-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2005</code></td><td>FOUR-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2006</code></td><td>SIX-PER-EM SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2007</code></td><td>FIGURE SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2008</code></td><td>PUNCTUATION SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2009</code></td><td>THIN SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x200A</code></td><td>HAIR SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x202F</code></td><td>NARROW NO-BREAK SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x205F</code></td><td>MEDIUM MATHEMATICAL SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x3000</code></td><td>IDEOGRAPHIC SPACE</td><td>Space Separator</td></tr>
+		 *     <tr><td><code>0x2028</code></td><td>LINE SEPARATOR</td><td>Line Separator</td></tr>
+		 *     <tr><td><code>0x2029</code></td><td>PARAGRAPH SEPARATOR</td><td>Paragraph Separator</td></tr>
+		 *     <tr><td><code>0x0009</code></td><td>CHARACTER TABULATION</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000A</code></td><td>LINE FEED</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000B</code></td><td>LINE TABULATION</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000C</code></td><td>FORM FEED</td><td>Other</td></tr>
+		 *     <tr><td><code>0x000D</code></td><td>CARRIAGE RETURN</td><td>Other</td></tr>
+		 *     <tr><td><code>0x0085</code></td><td>NEXT LINE</td><td>Other</td></tr>
+		 *     <tr><td><code>0x00A0</code></td><td>NO-BREAK SPACE</td><td>Other</td></tr>
+		 *  </table>
+
+		 *
+		 * @param charCode An integer that represents a character code.
+		 * Character codes are usually represented in hexadecimal format.
+		 * For example, the space character's character code can be
+		 * represented by the number <code>0x0020</code>.
+		 *
+		 * @return <code>true</code> if <code>charCode</code> is a whitespace character. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		static public function isWhitespace(charCode:int):Boolean
+		{			
+			return whiteSpaceObject[charCode];
+		}
+	}
+}
diff --git a/textLayout_core/src/flashx/textLayout/utils/GeometryUtil.as b/textLayout_core/src/flashx/textLayout/utils/GeometryUtil.as
new file mode 100755
index 0000000..b5e710f
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/utils/GeometryUtil.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 flashx.textLayout.utils
+{
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	/** 
+	 * Utilities for getting information about text geometry and bounds.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>GeometryUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 [ExcludeClass]
+	public final class GeometryUtil
+	{
+		/**
+		 * Returns an array of line/rectangle object pairs describing the highlight area of the text 
+		 * based on the content bounded within the indicies. The rectangles are the same as those which would be 
+		 * created if the text were selected. May return one or more pair per line.
+		 * 
+		 * 
+		 * @param range	- a TextRange describing the TextFlow as well as the beginning and end indicies
+		 * @return Array - An array of TextLine and Rectangle pairs. The objects can be referenced as:
+		 * 		obj.textLine - to access the TextLine object
+		 *		obj.rect - to access the rectangle describing the selection in TextLine coordinates
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * Example Usage:
+		 *  var theRect:Rectangle = returnArray[0].rect.clone(); 
+		 *  var textLine:TextLine = returnArray[0].textLine; 
+		 * 	var globalStart:Point = new Point(theRect.x, theRect.y);
+		 *  globalStart = textLine.localToGlobal(globalStart);
+		 *  globalStart = textLine.parent.globalToLocal(globalStart);
+		 *  theRect.x = globalStart.x;
+		 *  theRect.y = globalStart.y;
+		 * 
+		 *  [Make a new shape and draw the path into it. See flash.display.graphics]
+		 *  textLine.parent.addChild(newShape);
+		 */
+		public static function getHighlightBounds(range:TextRange):Array
+		{
+			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
+			if (!flowComposer)
+				return null;
+			
+			
+			var resultShapes:Array = new Array();
+			
+			var begLine:int = flowComposer.findLineIndexAtPosition(range.absoluteStart);
+			var endLine:int = range.absoluteStart == range.absoluteEnd ? begLine : flowComposer.findLineIndexAtPosition(range.absoluteEnd);
+			
+			// watch for going past the end
+			if (endLine >= flowComposer.numLines)
+				endLine = flowComposer.numLines-1;
+					
+			var prevLine:TextFlowLine = begLine > 0 ? flowComposer.getLineAt(begLine-1) : null;
+			var nextLine:TextFlowLine;
+
+			var line:TextFlowLine = flowComposer.getLineAt(begLine); 
+			
+			
+			for (var curLineIndex:int = begLine; curLineIndex <= endLine; curLineIndex++)
+			{
+				nextLine = curLineIndex != (flowComposer.numLines - 1) ? flowComposer.getLineAt(curLineIndex + 1) : null;
+				
+				var mainRects:Array = new Array();
+				var tcyRects:Array = new Array();
+				
+				var heightAndAdj:Array = line.getRomanSelectionHeightAndVerticalAdjustment(prevLine, nextLine);
+				
+				var textLine:TextLine = line.getTextLine();
+				line.calculateSelectionBounds(textLine, mainRects, 
+					range.absoluteStart < line.absoluteStart ? line.absoluteStart - line.paragraph.getAbsoluteStart()
+ 															 : range.absoluteStart - line.paragraph.getAbsoluteStart(), 
+					range.absoluteEnd > (line.absoluteStart + line.textLength) ? line.absoluteStart + line.textLength - line.paragraph.getAbsoluteStart()
+																			   : range.absoluteEnd - line.paragraph.getAbsoluteStart(), 
+					range.textFlow.computedFormat.blockProgression, heightAndAdj);
+				
+					
+				for each(var rect:Rectangle in mainRects)
+				{
+					var obj:Object = new Object();
+					obj.textLine = textLine;
+					obj.rect = rect.clone();
+					
+					resultShapes.push(obj);
+				}
+				
+				var temp:TextFlowLine = line;
+				line = nextLine;
+				prevLine = temp;
+				
+			}
+			
+			return resultShapes;
+		}
+	}
+	
+}
\ No newline at end of file
diff --git a/textLayout_core/src/flashx/textLayout/utils/LocaleUtil.as b/textLayout_core/src/flashx/textLayout/utils/LocaleUtil.as
new file mode 100755
index 0000000..0e46618
--- /dev/null
+++ b/textLayout_core/src/flashx/textLayout/utils/LocaleUtil.as
@@ -0,0 +1,237 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.utils
+{
+	import flash.text.engine.JustificationStyle;
+	import flash.text.engine.TextBaseline;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.JustificationRule;
+	import flashx.textLayout.formats.LeadingModel;
+	import flashx.textLayout.tlf_internal;
+	
+	
+	use namespace tlf_internal;
+	/** 
+	 * Utilities for managing and getting information about Locale based defaults.
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>LocaleUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	[ExcludeClass]
+	public final class LocaleUtil
+	{
+		public function LocaleUtil()
+		{
+		}
+		
+		
+		/** @private */
+		static private var _localeSettings:Dictionary = null;
+		static private var _lastLocaleKey:String = "";
+		static private var _lastLocale:LocaleSettings = null;
+		
+		static public function justificationRule(locale:String):String 
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.justificationRule;
+		}
+		
+		static public function justificationStyle(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.justificationStyle;
+		}
+		
+		static public function leadingModel(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.leadingModel;
+		}
+		
+		
+		static public function dominantBaseline(locale:String):String
+		{
+			var localeSet:LocaleSettings = fetchLocaleSet(locale);
+			CONFIG::debug{ assert(localeSet != null, "Failed to get LocaleSettings from locale! locale = " + locale); }
+			
+			return localeSet.dominantBaseline;
+		}
+		
+		/** @private */
+		static private function initializeDefaultLocales():void
+		{
+			CONFIG::debug{ assert(_localeSettings == null, "Should not call initializeDefaultLocales when dictionary exists!"); }
+			_localeSettings = new Dictionary();
+			
+			try
+			{
+				var locale:LocaleSettings = addLocale("en");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'en'!"); }
+	
+				locale.justificationRule = JustificationRule.SPACE;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.ROMAN_UP;
+				locale.dominantBaseline = TextBaseline.ROMAN;
+				
+				locale = addLocale("ja");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'ja'!"); }
+	
+				locale.justificationRule = JustificationRule.EAST_ASIAN;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.IDEOGRAPHIC_TOP_DOWN;
+				locale.dominantBaseline = TextBaseline.IDEOGRAPHIC_CENTER;
+				
+				locale = addLocale("zh");
+				CONFIG::debug{ assert(locale != null, "Failed to create new locale for 'zh'!"); }
+	
+				locale.justificationRule = JustificationRule.EAST_ASIAN;
+				locale.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU;
+				locale.leadingModel = LeadingModel.IDEOGRAPHIC_TOP_DOWN;
+				locale.dominantBaseline = TextBaseline.IDEOGRAPHIC_CENTER;
+			}	
+			catch(e:ArgumentError)
+			{
+				trace(e);
+				return;
+			}		
+			finally
+			{
+				return;
+			}
+		}
+		
+		/** @private */
+		static private function addLocale(locale:String):LocaleSettings
+		{
+			CONFIG::debug{ assert(_localeSettings[locale] == null, "Cannot add a new locale property set when it already exists.  Locale == " + locale); }
+			_localeSettings[locale] = new LocaleSettings();
+			return _localeSettings[locale];
+		}
+		
+		/** @private */
+		static private function getLocale(locale:String):LocaleSettings
+		{
+			var lowerLocale:String = locale.toLowerCase();
+			if(lowerLocale.indexOf("en") == 0)
+				return _localeSettings["en"];
+			else if(lowerLocale.indexOf("ja") == 0)
+				return _localeSettings["ja"];
+			else if(lowerLocale.indexOf("zh") == 0)
+				return _localeSettings["zh"];
+			else //default
+				return _localeSettings["en"];
+		}
+		
+		/** @private */
+		static private function fetchLocaleSet(locale:String):LocaleSettings
+		{
+			if(_localeSettings == null)
+				initializeDefaultLocales();
+			
+			var localeSet:LocaleSettings = null;
+			if(locale == _lastLocaleKey)
+				localeSet = _lastLocale;
+			else
+			{
+				localeSet = getLocale(locale);
+				
+				//update the last locale data
+				_lastLocale = localeSet;
+				_lastLocaleKey = locale;
+			}
+			return localeSet;
+		}
+	}
+	
+	
+}
+
+import flashx.textLayout.formats.JustificationRule;
+import flash.text.engine.JustificationStyle;
+import flashx.textLayout.formats.LeadingModel;
+import flash.text.engine.TextBaseline;
+
+import flashx.textLayout.debug.assert;
+import flashx.textLayout.tlf_internal;
+import flashx.textLayout.formats.TextLayoutFormat;
+
+use namespace tlf_internal;
+
+internal class LocaleSettings
+{
+	public function LocaleSettings()
+	{}
+	
+	private var _justificationRule:String = null;
+	private var _justificationStyle:String = null;
+	private var _leadingModel:String = null;
+	private var _dominantBaseline:String = null;
+	
+	public function get justificationRule():String { return _justificationRule; }
+	public function set justificationRule(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.justificationRuleProperty.setHelper(_justificationRule,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid JustificationRule!"); }
+		
+		_justificationRule = setValue == null ? null : (setValue as String);
+	}
+	
+	public function get justificationStyle():String { return _justificationStyle; }
+	public function set justificationStyle(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.justificationStyleProperty.setHelper(_justificationStyle,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid LeadingDirection!"); }
+		
+		_justificationStyle = setValue == null ? null : (setValue as String);
+	}
+	
+	public function get leadingModel():String { return _leadingModel; }
+	public function set leadingModel(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.leadingModelProperty.setHelper(_leadingModel,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid JustificationStyle!"); }
+		
+		_leadingModel = setValue == null ? null : (setValue as String);
+	}
+	
+	
+	public function get dominantBaseline():String { return _dominantBaseline; }
+	public function set dominantBaseline(newValue:String):void 
+	{ 
+		var setValue:Object = TextLayoutFormat.dominantBaselineProperty.setHelper(_dominantBaseline,newValue);
+		//don't assert if the newValue is null, only if it is invalid
+		CONFIG::debug{ assert(newValue == null || setValue != null, "LocaleUtil should never be providing an invalid TextBaseline!"); }
+		
+		_dominantBaseline = setValue == null ? null : (setValue as String);
+	}
+}
\ No newline at end of file
diff --git a/textLayout_core/version.txt b/textLayout_core/version.txt
new file mode 100755
index 0000000..8374538
--- /dev/null
+++ b/textLayout_core/version.txt
@@ -0,0 +1,8 @@
+#Fri Jan 29 11:40:38 PST 2010
+buildType=Published
+flashplayer.latest.good.win=309
+flashplayer.latest.good.lnx=584
+version=1.0
+flashplayer.latest.good.mac=307
+flashplayer.version=10.1.50.302
+build=595
diff --git a/textLayout_edit/.actionScriptProperties b/textLayout_edit/.actionScriptProperties
new file mode 100755
index 0000000..bee8a68
--- /dev/null
+++ b/textLayout_edit/.actionScriptProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<actionScriptProperties mainApplicationPath="textLayout_edit.as" projectUUID="741cd106-3543-4625-982d-b703fe2bcdf5" version="6">
+  <compiler additionalCompilerArguments="-locale en_US -load-config+=../../config.xml" autoRSLOrdering="true" copyDependentFiles="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+    <compilerSourcePath/>
+    <libraryPath defaultLinkType="0">
+      <libraryPathEntry kind="3" linkType="4" path="/textLayout_conversion/bin/textLayout_conversion.swc" useDefaultLinkType="true"/>
+      <libraryPathEntry kind="3" linkType="4" path="/textLayout_core/bin/textLayout_core.swc" useDefaultLinkType="true"/>
+      <libraryPathEntry kind="4" path="">
+        <excludedEntries>
+          <libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="4" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/rpc_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="rpc_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="2" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/framework_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="framework_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="1" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/textLayout.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/textLayout_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="textLayout_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="3" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/spark_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="spark_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
+        </excludedEntries>
+      </libraryPathEntry>
+    </libraryPath>
+    <sourceAttachmentPath/>
+  </compiler>
+  <applications>
+    <application path="textLayout_edit.as"/>
+  </applications>
+  <modules/>
+  <buildCSSFiles/>
+</actionScriptProperties>
diff --git a/textLayout_edit/.flexLibProperties b/textLayout_edit/.flexLibProperties
new file mode 100755
index 0000000..7bd5bd6
--- /dev/null
+++ b/textLayout_edit/.flexLibProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<flexLibProperties includeAllClasses="false" version="3">
+  <includeClasses>
+    <classEntry path="flashx.textLayout.EditClasses"/>
+  </includeClasses>
+  <includeResources/>
+  <namespaceManifests/>
+</flexLibProperties>
diff --git a/textLayout_edit/.project b/textLayout_edit/.project
new file mode 100755
index 0000000..f357d31
--- /dev/null
+++ b/textLayout_edit/.project
@@ -0,0 +1,36 @@
+<?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.
+-->
+<projectDescription>
+	<name>textLayout_edit</name>
+	<comment></comment>
+	<projects>
+		<project>textLayout_conversion</project>
+		<project>textLayout_core</project>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.adobe.flexbuilder.project.flexbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
+		<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
+	</natures>
+</projectDescription>
diff --git a/textLayout_edit/src/flash/text/ime/CompositionAttributeRange.as b/textLayout_edit/src/flash/text/ime/CompositionAttributeRange.as
new file mode 100755
index 0000000..9473ae7
--- /dev/null
+++ b/textLayout_edit/src/flash/text/ime/CompositionAttributeRange.as
@@ -0,0 +1,121 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flash.text.ime
+{
+
+//
+// CompositionAttributeRange
+//
+
+/**
+* The CompositionAttributeRange class represents a range of composition attributes for use with IME events. 
+* For example, when editing text in the IME, the text is divided by the IME into composition ranges.
+* These composition ranges are flagged as selected (i.e. currently being lengthened, shortened, or edited),
+* and/or converted (i.e. they have made one pass through the IME dictionary lookup already).
+*
+* <p>By convention, the client should adorn these composition ranges with underlining or hiliting according to
+* the flags.</p>
+*
+* <p>For example:</p>
+* <listing>
+*      !converted              = thick gray underline (raw text)
+*      !selected &#38;&#38; converted  = thin black underline
+*       selected &#38;&#38; converted  = thick black underline
+* </listing>
+* @playerversion Flash 10.1
+ * @playerversion AIR 1.5
+* @langversion 3.0
+*/
+public final class CompositionAttributeRange
+{
+	/**
+	 * The relative start from the beginning of the inline edit session
+	 * i.e. 0 = the start of the text the IME can see (there may be text 
+	 * before that in the edit field)
+	 * 
+	 * @helpid 
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 * 
+	*/
+	public var relativeStart:int;
+
+	/**
+	 * The relative end of the composition clause, relative to the beginning
+	 * of the inline edit session.
+	 * i.e. 0 = the start of the text the IME can see (there may be text 
+	 * before that in the edit field)
+	 * 
+	 * @helpid 
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 * 
+	*/
+	public var relativeEnd:int;
+
+	/**
+	 * The selected flag, meaning this composition clause is active and 
+	 * being lengthened or shortened or edited with the IME, and the neighboring
+	 * clauses are not.
+	 * 
+	 * @helpid 
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 * 
+	*/
+	public var selected:Boolean;
+
+	/**
+	 * The converted flag, meaning this clause has been processed by the IME
+	 * and is awaiting acceptance/confirmation by the user
+	 * 
+	 * @helpid 
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 * 
+	*/
+	public var converted:Boolean;
+
+	// Constructor
+	/**
+	 * Creates a CompositionAttributeRange object.
+	 *
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 * 
+	 * @param relativeStart  The zero based index of the first character included in the character range.
+	 * @param relativeEnd  The zero based index of the last character included in the character range.
+	 * @param selected  The selected flag
+	 * @param converted  The converted flag
+	 *
+	 * @tiptext Constructor for CompositionAttributeRange objects.
+	 */	
+	public function CompositionAttributeRange(relativeStart:int, relativeEnd:int, selected:Boolean, converted:Boolean):void
+	{
+		this.relativeStart = relativeStart;
+		this.relativeEnd = relativeEnd;
+		this.selected = selected;
+		this.converted = converted;
+	}
+} // end of class
+} // end of package
diff --git a/textLayout_edit/src/flash/text/ime/IIMEClient.as b/textLayout_edit/src/flash/text/ime/IIMEClient.as
new file mode 100755
index 0000000..ec7ea82
--- /dev/null
+++ b/textLayout_edit/src/flash/text/ime/IIMEClient.as
@@ -0,0 +1,186 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flash.text.ime
+{
+
+import flash.geom.Rectangle;
+
+//
+// IIMEClient
+//
+/**
+ * Dispatched when the user begins to use an IME (input method editor).
+ * @eventType flash.events.IMEEvent.IME_START_COMPOSITION
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+[Event(name="imeStartComposition", type="flash.IMEEvent.IME_START_COMPOSITION")]
+
+/**
+ * Dispatched when the user enters text. For IME (input method editor) clients, the receiver should 
+ * insert the string contained in the event object's <code>text</code> property at the current insertion point.
+ * @eventType flash.events.TextEvent.TEXT_INPUT
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */
+[Event(name="textInput", type="flash.TextEvent.TEXT_INPUT")]
+
+/**
+* Interface for IME (input method editor) clients.  Components based on the flash.text.engine package must implement 
+* this interface to support editing text inline using an IME. This interface is not used with TextField objects. 
+* TextLayoutFramework (TLF) uses this interface to support inline IME, so clients using TLF do not need to implement this 
+* interface. 
+* <p>To support inline IME, set the <code>imeClient</code> property of an <code>ImeEvent.IME_START_COMPOSITION</code> event to
+* an object which implements this interface.</p>
+*
+* @see flash.text.ime.CompositionAttributeRange
+* @see flash.events.ImeEvent:imeClient
+* 
+* @playerversion Flash 10.1
+* @playerversion AIR 1.5
+* @langversion 3.0
+*/
+public interface IIMEClient
+{
+	/**
+	* Callback for updating the contents of the inline editing session.
+	* This gets called whenever the text being edited with the IME has changed
+	* and its contents are used by the client to redraw the entire inline edit session.
+	* 
+	* @playerversion Flash 10.1
+	* @langversion 3.0
+	* 
+	* @param text  contains the text of the inline edit session from the IME
+	* @param attributes  contains an array of composition clauses with adornment info 
+	* @param relativeSelectionStart  start of the inline session relative to the start of the text object
+	* @param relativeSelectionEnd  end of the inline session relative to the start of the text object
+	*/
+	function updateComposition(text:String, attributes:Vector.<CompositionAttributeRange>,
+								compositionStartIndex:int, compositionEndIndex:int):void;
+								
+	/**
+	* Use this callback to end the inline editing session and confirm the text.
+	* 
+	* @playerversion Flash 10.1
+	* @langversion 3.0
+	* 
+	* @param text  the final state of the text in the inline session (the text that got confirmed).
+	* @param preserveSelection  when true, you should not reset the current selection to the end of the confirmed text.
+	*/
+	function confirmComposition(text:String = null, preserveSelection:Boolean = false):void;
+
+	/**
+	* This callback is used by the IME to query the bounding box of the text being edited with the IME client.
+	* Use this method to place the candidate window and set the mouse cursor in the IME client when the mouse is over the 
+	* text field or other component that supports IME.
+	* 
+	* @playerversion Flash 10.1
+	* @langversion 3.0
+	* 
+	* @param startIndex an integer that specifies the starting location of the range of text for which you need to measure the bounding box.
+	* @param endIndex Optional; an integer that specifies the ending location of the range of text for which you need to measure the bounding box.
+	*
+	* @return  the bounding box of the specified range of text, or <code>null</code> if either or both of the indexes are invalid.
+	* The same value should be returned independant of whether <code>startIndex</code> is greater or less than <code>endIndex</code>.
+	*/
+	function getTextBounds(startIndex:int, endIndex:int):Rectangle;
+
+	/** 
+	 * The zero-based character index value of the start of the current edit session text (i.e.
+	 * all text in the inline session that is still not yet confirmed to the document).
+	 *
+	 * @return the index of the first character of the composition, or <code>-1</code> if there is no active composition.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function get compositionStartIndex():int;
+
+	/** 
+	 * The zero-based character index value of the end of the current edit session text (i.e.
+	 * all text in the inline session that is still not yet confirmed to the document).
+	 *
+	 * @return the index of the last character of the composition, or <code>-1</code> if there is no active composition.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function get compositionEndIndex():int;
+
+	/** 
+	 * Indicates whether the text in the component is vertical or not.  This will affect the positioning
+	 * of the candidate window (beside vertical text, below horizontal text).
+	 *
+	 * @return <code>true</code> if the text is vertical, otherwise false.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+    function get verticalTextLayout():Boolean;
+
+	/** 
+	 * The zero-based character index value of the first character in the current selection.
+	 *
+	 * @return the index of the character at the anchor end of the selection, or <code>-1</code> if no text is selected.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function get selectionAnchorIndex():int;
+
+	/** 
+	 * The zero-based character index value of the last character in the current selection.
+	 *
+	 * @return the index of the character at the active end of the selection, or <code>-1</code> if no text is selected.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function get selectionActiveIndex():int;
+    
+	/** 
+	 * Sets the range of selected text in the component.
+	 * If either of the arguments is out of bounds the selection should not be changed.
+	 * 
+	 * @param anchorIndex The zero-based index value of the character at the anchor end of the selection
+	 * @param activeIndex The zero-based index value of the character at the active end of the selection.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function selectRange(anchorIndex:int, activeIndex:int):void;
+    
+	/** 
+	 * Gets the specified range of text from the component.  This method is called during IME reconversion.
+	 * 
+	 * @param startIndex an integer that specifies the starting location of the range of text to be retrieved.
+	 * @param endIndex an integer that specifies the ending location of the range of text to be retrieved.
+	 * 
+	 * @return The requested text, or <code>null</code> if no text is available in the requested range
+	 * or if either or both of the indexes are invalid.  The same value should be returned 
+	 * independant of whether <code>startIndex</code> is greater or less than <code>endIndex</code>.
+	 * 
+	 * @playerversion Flash 10.1
+	 * @langversion 3.0
+	 */
+	function getTextInRange(startIndex:int, endIndex:int):String;
+} // end of class
+} // end of package
diff --git a/textLayout_edit/src/flashx/textLayout/EditClasses.as b/textLayout_edit/src/flashx/textLayout/EditClasses.as
new file mode 100755
index 0000000..f6cce19
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/EditClasses.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 flashx.textLayout
+{
+	internal class EditClasses
+	{
+		import flash.text.ime.CompositionAttributeRange; flash.text.ime.CompositionAttributeRange;
+		import flash.text.ime.IIMEClient; flash.text.ime.IIMEClient;
+		
+		import flashx.textLayout.container.TextContainerManager; TextContainerManager;
+		
+		import flashx.textLayout.events.FlowOperationEvent; FlowOperationEvent;
+		import flashx.textLayout.events.SelectionEvent; SelectionEvent;
+ 
+		import flashx.textLayout.edit.ElementRange; ElementRange;
+		import flashx.textLayout.edit.IEditManager; IEditManager;
+		import flashx.textLayout.edit.Mark; Mark;
+		import flashx.textLayout.edit.SelectionManager; SelectionManager;
+
+		import flashx.textLayout.edit.TextScrap; TextScrap;
+
+		import flashx.textLayout.operations.ApplyFormatOperation; ApplyFormatOperation;
+		import flashx.textLayout.operations.ApplyFormatToElementOperation; ApplyFormatToElementOperation;
+		import flashx.textLayout.operations.ApplyLinkOperation; ApplyLinkOperation;
+		import flashx.textLayout.operations.ApplyTCYOperation; ApplyTCYOperation;
+		import flashx.textLayout.operations.ApplyElementIDOperation; ApplyElementIDOperation;
+		import flashx.textLayout.operations.ApplyElementStyleNameOperation; ApplyElementStyleNameOperation;
+		import flashx.textLayout.operations.ClearFormatOperation; ClearFormatOperation;
+		import flashx.textLayout.operations.ClearFormatOnElementOperation; ClearFormatOnElementOperation;
+		import flashx.textLayout.operations.CompositeOperation; CompositeOperation;
+		import flashx.textLayout.operations.CopyOperation; CopyOperation;
+		import flashx.textLayout.operations.CutOperation; CutOperation;
+		import flashx.textLayout.operations.DeleteTextOperation; DeleteTextOperation;
+		import flashx.textLayout.operations.FlowOperation; FlowOperation;
+		import flashx.textLayout.operations.InsertInlineGraphicOperation; InsertInlineGraphicOperation;
+		import flashx.textLayout.operations.InsertTextOperation; InsertTextOperation;
+		import flashx.textLayout.operations.PasteOperation; PasteOperation;
+		import flashx.textLayout.operations.RedoOperation; RedoOperation;
+		import flashx.textLayout.operations.ApplyElementUserStyleOperation; ApplyElementUserStyleOperation;
+		import flashx.textLayout.operations.SplitParagraphOperation; SplitParagraphOperation;
+		import flashx.textLayout.operations.UndoOperation; UndoOperation;
+
+		import flashx.textLayout.utils.NavigationUtil; NavigationUtil;
+		
+		import flashx.undo.IOperation; flashx.undo.IOperation;
+		import flashx.undo.IUndoManager; flashx.undo.IUndoManager;
+		import flashx.undo.UndoManager; flashx.undo.UndoManager;
+
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/container/TextContainerManager.as b/textLayout_edit/src/flashx/textLayout/container/TextContainerManager.as
new file mode 100755
index 0000000..37126be
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/container/TextContainerManager.as
@@ -0,0 +1,2241 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+	import flash.display.DisplayObject;
+	import flash.display.InteractiveObject;
+	import flash.display.Sprite;
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.EventDispatcher;
+	import flash.events.FocusEvent;
+	import flash.events.IMEEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.TextEvent;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBlock;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.ui.ContextMenu;
+	import flash.ui.ContextMenuClipboardItems;
+	import flash.ui.Mouse;
+	import flash.ui.MouseCursor;
+	import flash.utils.Dictionary;
+	
+	import flashx.textLayout.compose.BaseCompose;
+	import flashx.textLayout.compose.ISWFContext;
+	import flashx.textLayout.compose.StandardFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.compose.TextLineRecycler;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.EditManager;
+	import flashx.textLayout.edit.EditingMode;
+	import flashx.textLayout.edit.IEditManager;
+	import flashx.textLayout.edit.IInteractionEventHandler;
+	import flashx.textLayout.edit.ISelectionManager;
+	import flashx.textLayout.edit.SelectionFormat;
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.IConfiguration;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.events.DamageEvent;
+	import flashx.textLayout.events.FlowOperationEvent;
+	import flashx.textLayout.events.SelectionEvent;
+	import flashx.textLayout.events.StatusChangeEvent;
+	import flashx.textLayout.events.TextLayoutEvent;
+	import flashx.textLayout.events.UpdateCompleteEvent;
+	import flashx.textLayout.external.WeakRef;
+	import flashx.textLayout.factory.StringTextLineFactory;
+	import flashx.textLayout.factory.TextFlowTextLineFactory;
+	import flashx.textLayout.factory.TextLineFactoryBase;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.FormatValue;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.property.EnumStringProperty;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	import flashx.undo.IUndoManager;
+	import flashx.undo.UndoManager;
+
+	use namespace tlf_internal;
+	/**
+	 *
+	 *  @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_BEGIN
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	[Event(name="flowOperationBegin", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	/**
+	 * 
+	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_END
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	 
+	[Event(name="flowOperationEnd", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	
+	/**
+	 * 
+	 * @eventType flashx.textLayout.events.FlowOperationEvent.FLOW_OPERATION_COMPLETE
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="flowOperationComplete", type="flashx.textLayout.events.FlowOperationEvent")]
+	
+	/** Dispatched whenever the selection is changed.  Primarily used to update selection-dependent user interface. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="selectionChange", type="flashx.textLayout.events.SelectionEvent")]
+	
+	/** Dispatched after every recompose. 
+	*
+	* @playerversion Flash 10
+	* @playerversion AIR 1.5
+	* @langversion 3.0
+	*/
+	
+	[Event(name="compositionComplete", type="flashx.textLayout.events.CompositionCompleteEvent")]
+	
+	/** Dispatched when the mouse is pressed down over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseDown", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse is released over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseUp", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse passes over any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="mouseMove", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	
+	/** Dispatched when the mouse first enters any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="rollOver", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when the mouse goes out of any link. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="rollOut", type="flashx.textLayout.events.FlowElementMouseEvent")]	
+	
+	/** Dispatched when any link is clicked. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="click", type="flashx.textLayout.events.FlowElementMouseEvent")]
+	
+	/** Dispatched when a InlineGraphicElement is resized due to having width or height as auto or percent 
+	 * and the graphic has finished loading. 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="inlineGraphicStatusChanged", type="flashx.textLayout.events.StatusChangeEvent")]
+	
+	/** Dispatched by a TextFlow object after text is scrolled within a controller container.  
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="scroll", type="flashx.textLayout.events.TextLayoutEvent")]
+	
+	/** Dispatched by a TextFlow object each time it is damaged 
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="damage", type="flashx.textLayout.events.DamageEvent")]
+
+	/** Dispatched by a TextFlow object each time a container has had new DisplayObjects added or updated as a result of composition.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	
+	[Event(name="updateComplete", type="flashx.textLayout.events.UpdateCompleteEvent")]
+		
+	[Exclude(name="getBaseSWFContext",kind="method")]
+	
+	[Exclude(name="callInContext",kind="method")]
+	/** Manages text in a container. Assumes that it manages all children of the container. 
+	 * Consider using TextContainerManager for better performance in cases where there is a 
+	 * one container per TextFlow, and the TextFlow is not the main focus, is static text, or
+	 * is infrequently selected. Good for text in form fields, for example.
+	 * 
+	 * @includeExample examples\TextContainerManager.as -noswf
+	 *
+ 	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 * 
+	 * @see ContainerController
+	 */			
+	public class TextContainerManager extends EventDispatcher implements ISWFContext, IInteractionEventHandler, ISandboxSupport
+	{
+		static private var _inputManagerTextFlowFactory:TextFlowTextLineFactory = new TextFlowTextLineFactory();
+		
+		// all events that are listened for need to be in this list.
+		static private const eventList:Array = [ 
+			FlowOperationEvent.FLOW_OPERATION_BEGIN,
+			FlowOperationEvent.FLOW_OPERATION_END,
+			FlowOperationEvent.FLOW_OPERATION_COMPLETE,
+			SelectionEvent.SELECTION_CHANGE,
+			CompositionCompleteEvent.COMPOSITION_COMPLETE,
+			MouseEvent.CLICK,		//from FlowElementMouseEvent
+			MouseEvent.MOUSE_DOWN,	//from FlowElementMouseEvent
+			MouseEvent.MOUSE_OUT,	//from FlowElementMouseEvent
+			MouseEvent.MOUSE_UP,	//from FlowElementMouseEvent
+			MouseEvent.MOUSE_OVER,	//from FlowElementMouseEvent
+			MouseEvent.MOUSE_OUT,	//from FlowElementMouseEvent
+			StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE,
+		 	TextLayoutEvent.SCROLL,
+			DamageEvent.DAMAGE,
+			UpdateCompleteEvent.UPDATE_COMPLETE
+		];
+		
+		/** Configuration to be used by the TextContainerManager.  This can only be set once and before the inputmanager is used.  */
+		static private var _inputManagerConfiguration:IConfiguration = null;
+		
+		/** The default configuration for this TextContainerManager. Column and padding attributes
+		 * are set to <code>FormatValue.INHERIT</code>.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 * 
+	 	 * @see flashx.textLayout.elements.IConfiguration IConfiguration
+	 	 * @see flashx.textLayout.formats.FormatValue#INHERIT FormatValue.INHERIT
+		 */
+		static public function get defaultConfiguration():IConfiguration
+		{
+			if (_inputManagerConfiguration == null)
+			{
+				var config:Configuration = new Configuration();
+				config.flowComposerClass = TextLineFactoryBase.getDefaultFlowComposerClass();
+				_inputManagerConfiguration = config;
+			}
+			return _inputManagerConfiguration; 
+		}
+		
+		static private var stringFactoryDictionary:Dictionary = new Dictionary(true);
+		static private function inputManagerStringFactory(config:IConfiguration):StringTextLineFactory
+		{
+			var factory:StringTextLineFactory = stringFactoryDictionary[config];
+			if (factory == null)
+			{
+				factory = new StringTextLineFactory(config);
+				stringFactoryDictionary[config] = factory;
+			}
+			return factory;
+		}
+		
+		/** Shared definition of the scrollPolicy property. @private */
+		static tlf_internal const editingModePropertyDefinition:EnumStringProperty = new EnumStringProperty("editingMode", EditingMode.READ_WRITE, false, null, 
+			EditingMode.READ_WRITE, EditingMode.READ_ONLY, EditingMode.READ_SELECT);	
+		
+		private var _container:Sprite;
+		private var _compositionWidth:Number;
+		private var _compositionHeight:Number;
+		
+		private var _text:String;
+		private var _textDamaged:Boolean;				// indicates the _text property needs updating when sourceState is SOURCE_TEXTFLOW
+		private var _lastSeparator:String;
+		
+		private var _hostFormat:ITextLayoutFormat;
+		private var _hostFormatHash:*;
+		
+		private var _contentTop:Number;
+		private var _contentLeft:Number;
+		private var _contentHeight:Number;
+		private var _contentWidth:Number;
+		
+		private var _horizontalScrollPolicy:String;
+		private var _verticalScrollPolicy:String;
+		
+		private var _swfContext:ISWFContext;
+		private var _config:IConfiguration;
+		
+		/** @private */
+		static tlf_internal const SOURCE_STRING:int = 0;
+		/** @private */
+		static tlf_internal const SOURCE_TEXTFLOW:int = 1;
+		
+		/** @private */
+		static tlf_internal const COMPOSE_FACTORY:int = 0;
+		/** @private */
+		static tlf_internal const COMPOSE_COMPOSER:int = 1;
+		
+		/** @private */
+		static tlf_internal const HANDLERS_NOTADDED:int  = 0;
+		/** @private */
+		static tlf_internal const HANDLERS_NONE:int      = 1;
+		/** @private */
+		static tlf_internal const HANDLERS_CREATION:int  = 2;
+		/** @private */
+		static tlf_internal const HANDLERS_ACTIVE:int    = 3;
+		
+		private var _sourceState:int;
+		private var _composeState:int;
+		private var _handlersState:int;
+		// track hasFocus.  Depending on various factors focus and mouseDown can occur in different order
+		private var _hasFocus:Boolean;
+		private var _editingMode:String;
+		private var _ibeamCursorSet:Boolean;
+		private var _interactionCount:int;
+		
+		/** @private */
+		tlf_internal function get sourceState():int
+		{ return _sourceState; }
+		/** @private */
+		tlf_internal function get composeState():int
+		{ return _composeState; }
+		/** @private */
+		tlf_internal function get handlersState():int
+		{ return _handlersState; }
+	
+		// Tracks damage when sourceState is SOURCE_STRING. TODO - Might be worthwhile to always set and clear this
+		private var _damaged:Boolean;			
+		private var _textFlow:TextFlow;
+		private var _needsRedraw:Boolean;
+		
+		/** Constructor function - creates a TextContainerManager instance.
+		 *
+		 * For best results:
+		 * <ol>
+		 *	<li>Start with TextContainerManager.defaultConfiguration and modify it</li>   
+		 *	<li>Share the same Configuration among many InputManagers</li>
+		 * </ol>
+		 *
+		 * @param container The DisplayObjectContainer in which to manage the text lines.
+		 * @param config - The IConfiguration instance to use with this TextContainerManager instance. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0	 	
+		 */
+		public function TextContainerManager(container:Sprite,configuration:IConfiguration =  null)
+		{
+			_container = container;
+			_compositionWidth = 100;
+			_compositionHeight = 100;
+			
+			_config = configuration ? configuration : defaultConfiguration;
+			_config = Configuration(_config).getImmutableClone();
+
+			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);
+
+			_damaged = true;
+			_needsRedraw = false;
+			_text = "";
+			_textDamaged = false;
+			
+			_sourceState = SOURCE_STRING;
+			_composeState = COMPOSE_FACTORY;
+			_handlersState = HANDLERS_NOTADDED;
+			_hasFocus = false;
+			
+			_editingMode = editingModePropertyDefinition.defaultValue as String;
+			_ibeamCursorSet = false;
+			_interactionCount = 0;
+			
+			if (_container is InteractiveObject)
+			{
+				_container.doubleClickEnabled = true;
+				// so the textlines can be swapped on the first click and a double click still works
+				_container.mouseChildren = false;
+				_container.focusRect = false;
+			}
+		}
+
+		/** Returns the container (DisplayObjectContainer) that holds the text that this TextContainerManager manages.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see ContainerController#container
+	 	 */
+	 	 
+		public function get container():Sprite
+		{ return _container; }
+		
+		/** Returns <code>true</code> if the content needs composing. 
+		 * 
+		 * @return	<code>true</code> if the content needs composing; <code>false</code> otherwise.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function isDamaged():Boolean
+		{ return _composeState == COMPOSE_FACTORY ? _damaged : _textFlow.flowComposer.isDamaged(_textFlow.textLength); }
+		
+		/** Editing mode of this TextContainerManager. Modes are reading only, reading and selection permitted, 
+		 * and editing (reading, selection, and writing)  permitted. Use the constant values of the EditingMode
+		 * class to set this property. 
+		 * <p>Default value is READ_WRITE.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see flashx.textLayout.edit.EditingMode EditingMode
+		 */
+		public function get editingMode():String
+		{ return _editingMode; }
+		public function set editingMode(val:String):void
+		{
+			var newMode:String = editingModePropertyDefinition.setHelper(_editingMode, val) as String;
+			
+			if (newMode != _editingMode)
+			{
+				if (composeState == COMPOSE_COMPOSER)
+				{
+					_editingMode = newMode;
+					invalidateInteractionManager();
+				}
+				else
+				{
+					removeActivationEventListeners();
+					_editingMode = newMode;
+					// there is no way to turn it on here if going from READ_ONLY to editable and mouse is over the inputmanager field
+					if (_editingMode == EditingMode.READ_ONLY)
+						removeIBeamCursor();
+					addActivationEventListeners();
+				}
+			}
+		}
+		 		
+		/**
+		 * Returns the current text using a separator between paragraphs.
+		 * The separator can be specified with the <code>separator</code>
+		 * argument. The default value of the <code>separator</code> argument
+		 * is the Unicode character <code>'PARAGRAPH SEPARATOR' (U+2029)</code>.
+		 *
+		 * <p>Calling the setter discards any attached TextFlow. Any selection is lost.</p>
+		 * 
+		 * @param separator String to set between paragraphs.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		public function getText(separator:String = '\u2029'):String
+		{
+			if (_sourceState == SOURCE_STRING)
+				return _text;
+
+			if (_textDamaged || _lastSeparator != separator)
+			{
+				_text = "";
+				var firstLeaf:FlowLeafElement = _textFlow.getFirstLeaf();
+				if (firstLeaf != null)
+				{
+					var para:ParagraphElement = firstLeaf.getParagraph();
+					while (para)
+					{
+						var nextPara:ParagraphElement = para.getNextParagraph();
+						_text += para.getText();
+						_text += nextPara ? separator : "";
+						para = nextPara;
+					}
+				}
+				_textDamaged = false;
+				_lastSeparator = separator;
+			}
+			return _text;
+		}
+		/**
+		 * Sets the <code>text</code> property to the specified String.
+		 *
+		 * Discards any attached TextFlow. Any selection is lost.
+		 * 
+		 * @param str the String to set
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		public function setText(text:String):void
+		{
+			var hadPreviousSelection:Boolean = false;
+
+			if (_sourceState == SOURCE_TEXTFLOW)
+			{
+				if (_textFlow.interactionManager && _textFlow.interactionManager.hasSelection())
+					hadPreviousSelection = true;
+				removeTextFlowListeners();
+				if (_textFlow.flowComposer)
+					_textFlow.flowComposer.removeAllControllers();
+				_textFlow = null;
+				_sourceState = SOURCE_STRING;
+				_composeState = COMPOSE_FACTORY;
+				if (_container is InteractiveObject)
+					_container.mouseChildren = false;
+				addActivationEventListeners();
+			}
+			_text = text ? text : ""; 
+			_damaged = true;
+			_textDamaged = false;
+			
+			// Generate a damage event 
+			dispatchEvent(new DamageEvent(DamageEvent.DAMAGE, false, false, null, 0, _text.length));
+			
+			// generate a selection changed event
+			if (hadPreviousSelection)
+				dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, null));
+			
+			if (_hasFocus)
+				requiredFocusInHandler(null);
+		}
+				
+		/** Sets the format when display just a string.  If displaying a TextFlow this has no immediate effect.  The supplied ITextLayoutFormat is not copied.  Modifying it without calling this setter has indeterminate effects. */
+		public function get hostFormat():ITextLayoutFormat
+		{ return _hostFormat; }
+		public function set hostFormat(val:ITextLayoutFormat):void
+		{
+			_hostFormat = val;
+			_hostFormatHash = undefined;
+			
+			if (_sourceState == SOURCE_TEXTFLOW)
+				_textFlow.hostFormat = _hostFormat;
+			if (_composeState == COMPOSE_FACTORY)
+				_damaged = true;
+		}
+		
+		/** Returns the horizontal extent allowed for text inside the container. The value is specified in pixels.
+		 * 
+		 * <p>After setting this property, the text in the container is damaged and requires composing.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0  
+	 	 */
+		public function get compositionWidth():Number
+		{ return _compositionWidth; }
+		public function set compositionWidth(val:Number):void
+		{
+			if (_compositionWidth == val || (isNaN(_compositionWidth) && isNaN(val)))
+				return;
+			_compositionWidth = val; 
+			if (_composeState == COMPOSE_COMPOSER)
+			{
+				getController().setCompositionSize(_compositionWidth,_compositionHeight);
+			}
+			else
+			{
+				_damaged = true; 
+			}
+		}
+	
+		/** Returns the vertical extent allowed for text inside the container. The value is specified in pixels. 
+		 * <p>After setting this property, the text in the container is damaged and requires composing.</p>
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+	 	 
+		public function get compositionHeight():Number
+		{ return _compositionHeight; }
+		public function set compositionHeight(val:Number):void
+		{
+			if (_compositionHeight == val || (isNaN(_compositionHeight) && isNaN(val)))
+				return;
+			_compositionHeight = val; 
+			if (_composeState == COMPOSE_COMPOSER)
+			{
+				getController().setCompositionSize(_compositionWidth,_compositionHeight);
+			}
+			else
+			{
+				_damaged = true; 
+			}
+		}
+		
+		/** The Configuration object for this TextContainerManager. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.IConfiguration IConfiguration
+	 	 */
+		public function get configuration():IConfiguration
+		{ return _config; }
+			
+		/** Creates a rectangle that shows where the last call to either the <code>compose()</code> 
+		 * method or the <code>updateContainer()</code> method placed the text.
+		 *
+		 * @return  the bounds of the content
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see #compose()
+	 	 * @see #updateContainer()
+		 */
+		public function getContentBounds():Rectangle
+		{
+			if (_composeState == COMPOSE_FACTORY)
+				return new Rectangle(_contentLeft, _contentTop, _contentWidth, _contentHeight);
+			var controller:ContainerController = getController();
+			return controller.getContentBounds();
+		}	
+		
+		/** The current TextFlow. Converts this to a full TextFlow representation if it 
+		 * isn't already one. 
+		 *
+		 * @return 	the current TextFlow object
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function getTextFlow():TextFlow
+		{
+			if (_sourceState != SOURCE_TEXTFLOW)
+			{
+				var wasDamaged:Boolean = isDamaged();
+				convertToTextFlow();
+				if (!wasDamaged)
+					updateContainer();
+			}
+			return _textFlow;
+		}
+
+		/** Sets a TextFlow into this TextContainerManager replacing any existing TextFlow and discarding the 
+		 * current text. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function setTextFlow(textFlow:TextFlow):void
+		{
+			if (textFlow == null)
+			{
+				setText(null);
+				return;
+			}
+			if (_sourceState == SOURCE_TEXTFLOW)
+			{
+				removeTextFlowListeners();
+				if (_textFlow.flowComposer)
+					_textFlow.flowComposer.removeAllControllers();
+			}
+				
+			_textFlow = textFlow;
+			_textFlow.hostFormat = hostFormat;
+			_sourceState = SOURCE_TEXTFLOW;
+			_composeState = textFlow.interactionManager || textFlow.mustUseComposer() ? COMPOSE_COMPOSER : COMPOSE_FACTORY;
+			_textDamaged = true;
+			addTextFlowListeners();
+			
+			if (_composeState == COMPOSE_COMPOSER)
+			{
+				// Possible issue - this clear call could be delayed until updateToController
+				_container.mouseChildren = true;
+				clearContainerChildren(true);
+				clearComposedLines();
+				_textFlow.flowComposer = new StandardFlowComposer();
+				_textFlow.flowComposer.swfContext = _swfContext;
+				var controller:TMContainerController = new TMContainerController(_container,_compositionWidth,_compositionHeight,this);
+				_textFlow.flowComposer.addController(controller);
+				
+				invalidateInteractionManager();
+				
+				// always start with an empty selection
+				if (_textFlow.interactionManager)
+					_textFlow.interactionManager.selectRange(-1,-1);
+			}
+			else
+				_damaged = true;
+			
+			if (_hasFocus)
+				requiredFocusInHandler(null);
+			
+			addActivationEventListeners();
+		}
+		
+		/** 
+		 * Controls whether the factory generates all text lines or stops when the container bounds are filled.
+		 * 
+		 * @copy flashx.textLayout.container.ContainerController#horizontalScrollPolicy 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+	 	public function get horizontalScrollPolicy():String
+		{
+			return _horizontalScrollPolicy;
+		}
+		public function set horizontalScrollPolicy(scrollPolicy:String):void
+		{
+			_horizontalScrollPolicy = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_horizontalScrollPolicy, scrollPolicy) as String;
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().horizontalScrollPolicy = _horizontalScrollPolicy;
+			else
+				_damaged = true;
+		}
+		
+		/** 
+		 * Controls whether the factory generates all text lines or stops when the container bounds are filled.
+		 * 
+		 * @copy flashx.textLayout.container.ContainerController#verticalScrollPolicy 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+	 	 
+		public function get verticalScrollPolicy():String
+		{
+			return _verticalScrollPolicy;
+		}
+		public function set verticalScrollPolicy(scrollPolicy:String):void
+		{
+			_verticalScrollPolicy = ScrollPolicy.scrollPolicyPropertyDefinition.setHelper(_verticalScrollPolicy, scrollPolicy) as String;
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().verticalScrollPolicy = _verticalScrollPolicy;
+			else
+				_damaged = true;
+		}
+			
+		/** 
+		 * @copy flashx.textLayout.container.ContainerController#horizontalScrollPosition
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		public function get horizontalScrollPosition():Number
+		{ return _composeState == COMPOSE_COMPOSER ? getController().horizontalScrollPosition : 0; }
+		public function set horizontalScrollPosition(val:Number):void
+		{ 
+			if (val == 0 && _composeState == COMPOSE_FACTORY)
+				return;
+			if (_composeState != COMPOSE_COMPOSER)
+				convertToTextFlowWithComposer();
+			getController().horizontalScrollPosition = val;
+		}
+		
+		/** 
+		 * @copy flashx.textLayout.container.ContainerController#verticalScrollPosition 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		public function get verticalScrollPosition():Number
+		{ return _composeState == COMPOSE_COMPOSER ? getController().verticalScrollPosition : 0; }
+		public function set verticalScrollPosition(val:Number):void
+		{
+			if (val == 0 && _composeState == COMPOSE_FACTORY)
+				return;
+			if (_composeState != COMPOSE_COMPOSER)
+				convertToTextFlowWithComposer();
+			getController().verticalScrollPosition = val;
+		}
+
+		/** 
+		* @copy flashx.textLayout.container.ContainerController#getScrollDelta() 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+	 	*/
+		public function getScrollDelta(numLines:int):Number
+		{
+			if (_composeState != COMPOSE_COMPOSER)
+				convertToTextFlowWithComposer();
+			return getController().getScrollDelta(numLines);
+		}
+		
+		/** 
+		* @copy flashx.textLayout.container.ContainerController#scrollToRange() 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+		* @langversion 3.0
+	 	*/
+	 	public function scrollToRange(activePosition:int,anchorPosition:int):void
+	 	{
+			if (_composeState != COMPOSE_COMPOSER)
+				convertToTextFlowWithComposer();
+			getController().scrollToRange(activePosition,anchorPosition);	 		
+	 	}
+
+		/** 
+		* Optional ISWFContext instance used to make FTE calls as needed in the proper swf context. 
+		*
+		* 
+		* @see flashx.textLayout.compose.ISWFContext
+		* 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0
+	 	*/
+ 	
+		public function get swfContext():ISWFContext
+		{ return _swfContext; }
+		public function set swfContext(context:ISWFContext):void
+		{ 
+			_swfContext = context;
+			if (_composeState == COMPOSE_COMPOSER)
+				_textFlow.flowComposer.swfContext = _swfContext;
+			else
+				_damaged = true;
+		}
+		
+		/** @private - TextContainerManager wraps an underlying swfcontext - tell it to FlowComposerBase so it can avoid extra invalidation */
+		public function getBaseSWFContext():ISWFContext
+		{ return _swfContext; }
+		
+		/** @private - this is part of a performance optimziation for reusing existing TextLines in place iff recreateTextLine is available. */
+	    public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
+		{
+			var textBlock:TextBlock = thisArg as TextBlock;
+			if (textBlock)
+			{
+			 	if (fn == textBlock.createTextLine)
+					return createTextLine(textBlock,argsArray);
+				if (Configuration.playerEnablesArgoFeatures && fn == thisArg["recreateTextLine"])
+					return recreateTextLine(textBlock,argsArray);
+			}
+	        if (returns)
+	            return fn.apply(thisArg, argsArray);
+	        fn.apply(thisArg, argsArray);
+		}
+		
+		/** 
+		 * Uses the <code>textBlock</code> parameter, and calls the <code>TextBlock.createTextLine()</code> method on it 
+		 * using the remaining parameters.
+		 * WARNING: modifies argsArray
+		 *  
+		 * @copy flash.text.engine.TextBlock
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		private function createTextLine(textBlock:TextBlock, argsArray:Array):TextLine
+		{
+			var swfContext:ISWFContext = _swfContext ? _swfContext : BaseCompose.globalSWFContext;
+			
+			CONFIG::debug { assert(Configuration.playerEnablesArgoFeatures,"Bad call to createTextLine"); }
+			if (_composeRecycledInPlaceLines < _composedLines.length)
+			{
+				var textLine:TextLine = _composedLines[_composeRecycledInPlaceLines++];
+
+				argsArray.splice(0,0,textLine);
+				return swfContext.callInContext(textBlock["recreateTextLine"],textBlock,argsArray);
+			}
+
+			return swfContext.callInContext(textBlock.createTextLine,textBlock,argsArray);
+		}
+
+		/** 
+		 * Uses the <code>textBlock</code> parameter, and calls the <code>FlowComposerBase.recreateTextLine()</code> method on it 
+		 * using the remaining parameters.
+		 *
+		 * @param textBlock The TextBlock to which the TextLine belongs.
+		 * @param textLine  The TextLine to be recreated.
+		 * @param previousLine Specifies the previously broken line after 
+		 *	which breaking is to commence. Can be null when breaking the first line.  
+		 * @param width Specifies the desired width of the line in pixels. The 
+		 * 	actual width may be less.  
+		 * @param lineOffset An optional parameter which specifies the difference in 
+		 *	pixels between the origin of the line and the origin of the tab stops. This can be used when lines are not aligned, 
+		 * 	but it is desirable for their tabs to be so. 
+		 * @param fitSomething An optional parameter that instructs the runtime to fit at least one 
+		 * 	character into the text line, no matter what width has been specified (even if width is zero or negative, which 
+		 * 	would otherwise result in an exception being thrown).  
+		 * @return The recreated TextLine instance.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		private function recreateTextLine(textBlock:TextBlock, argsArray:Array):TextLine
+		{
+			if (_composeRecycledInPlaceLines < _composedLines.length)
+			{
+				CONFIG::debug {assert(argsArray[0] != _composedLines[_composeRecycledInPlaceLines],"Bad args"); }
+				TextLineRecycler.addLineForReuse(argsArray[0]);	// not going to use this one
+				argsArray[0] = _composedLines[_composeRecycledInPlaceLines++];
+			}
+			var swfContext:ISWFContext = _swfContext ? _swfContext : BaseCompose.globalSWFContext;
+			return swfContext.callInContext(textBlock["recreateTextLine"],textBlock,argsArray);
+		}
+
+		
+		/** Returns the current ISelectionManager instance. Converts to TextFlow instance and creates one if necessary. 
+		 *
+		 * @return  the interaction manager for this TextContainerManager instance.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+	 	 * @see flashx.textLayout.edit.ISelectionManager ISelectionManager
+	 	 */
+		public function beginInteraction():ISelectionManager
+		{
+			++_interactionCount;
+			if (_composeState != COMPOSE_COMPOSER)
+				convertToTextFlowWithComposer();
+			return _textFlow.interactionManager;
+		}
+		
+		/** Terminates interaction. 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flashx.textLayout.edit.ISelectionManager ISelectionManager
+	 	 */
+		
+		public function endInteraction():void
+		{
+			--_interactionCount;
+		}
+		
+		/** Call this if you are editing, and want to reset the undo manager used for editing.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function invalidateUndoManager():void
+		{
+			if (_editingMode == EditingMode.READ_WRITE)
+				invalidateInteractionManager(true);
+		}
+		
+		
+		/** Call this if you change the selection formats (SelectionFormat) and want the interactionManager 
+		 * to update. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+	 	 */
+		public function invalidateSelectionFormats():void
+		{
+			invalidateInteractionManager();
+		}
+		
+		/** The interactionManager is invalid - update it. Clients should call this if they change the 
+		 * selectionFormats.  Its called automatically if editingMode is changed. */
+		private function invalidateInteractionManager(alwaysRecreateManager:Boolean = false):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+			{
+				var interactionManager:ISelectionManager = _textFlow.interactionManager;
+				var activePos:int = interactionManager ? interactionManager.activePosition : -1
+				var anchorPos:int = interactionManager ? interactionManager.anchorPosition : -1;
+
+				if (_editingMode == EditingMode.READ_ONLY)
+				{
+					if (interactionManager)
+						_textFlow.interactionManager = null;
+				}
+				else if (_editingMode == EditingMode.READ_WRITE)
+				{
+					if (alwaysRecreateManager || interactionManager == null || interactionManager.editingMode == EditingMode.READ_SELECT)
+					{
+						_textFlow.interactionManager = createEditManager(getUndoManager());
+						if (_textFlow.interactionManager is SelectionManager)
+							SelectionManager(_textFlow.interactionManager).cloneSelectionFormatState(interactionManager);
+					}
+				}
+				else if (_editingMode == EditingMode.READ_SELECT)
+				{
+					if (alwaysRecreateManager || interactionManager == null || interactionManager.editingMode == EditingMode.READ_WRITE)
+					{
+						_textFlow.interactionManager = createSelectionManager();
+						if (_textFlow.interactionManager is SelectionManager)
+							SelectionManager(_textFlow.interactionManager).cloneSelectionFormatState(interactionManager);
+					}
+				}
+				
+				interactionManager = _textFlow.interactionManager;
+				if (interactionManager)
+				{
+					interactionManager.unfocusedSelectionFormat  = getUnfocusedSelectionFormat();
+					interactionManager.focusedSelectionFormat    = getFocusedSelectionFormat();
+					interactionManager.inactiveSelectionFormat = getInactiveSelectionFormat();
+					interactionManager.selectRange(anchorPos,activePos);
+				}				
+			}
+		}
+		
+		/**Create a selection manager to use for selection. Override this method if you have a custom SelectionManager that you
+		 * want to use in place of the default.
+		 *
+		 * @return	a new SelectionManager instance.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		protected function createSelectionManager():ISelectionManager
+		{
+			return new SelectionManager();
+		}
+		
+		/**Create an edit manager to use for editing. Override this method if you have a custom EditManager that you
+		 * want to use in place of the default.
+		 *
+		 * @param  an IUndoManager instance for the EditManager being created.
+		 * @return	the editing manager for this TextContainerManager instance.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		protected function createEditManager(undoManager:flashx.undo.IUndoManager):IEditManager
+		{
+			return new EditManager(undoManager);
+		}
+		
+		private function getController():TMContainerController
+		{ return _textFlow.flowComposer.getControllerAt(0) as TMContainerController; }
+
+		private var _composedLines:Array = [];
+		
+		/** Return the TextLine at the index from array of composed lines.
+		 *
+		 * @param index	Finds the line at this index position in the text.
+		 *
+		 * @return 	the TextLine that occurs at the specified index.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		public function getLineAt(index:int):TextLine
+		{ 
+			// note: this method is not reliable for damaged text
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				// watch out for the empty TCM optimization and make a TextLine
+				if (_sourceState == SOURCE_STRING && _text.length == 0 && !_damaged && _composedLines.length == 0)
+				{
+					// flush the cache and force a recompose -- that will give us a TextLine
+					delete _emptyFormatCache[formatHash()];
+					
+					if (_needsRedraw)
+						compose();
+					else
+						updateContainer();
+					CONFIG::debug { assert(_composeState == COMPOSE_FACTORY,"no longer a factory??"); }
+				}
+				return _composedLines[index];
+			}
+			var tfl:TextFlowLine = _textFlow.flowComposer.getLineAt(index);
+			return tfl ? tfl.getTextLine(true) : null;
+		}
+		
+		/** @copy flashx.textLayout.compose.IFlowComposer#numLines 
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function get numLines():int
+		{ 
+			// note: this method is not reliable for damaged text
+			if (_composeState == COMPOSE_COMPOSER)
+				return _textFlow.flowComposer.numLines;
+			// watch out for possibly optimized zero length text
+			if (_sourceState == SOURCE_STRING && _text.length == 0)
+				return 1;
+			return _composedLines.length; 
+		}
+		
+		private function clearComposedLines():void
+		{
+			if (_composedLines)
+				_composedLines.length = 0;
+		}
+		
+		private function populateComposedLines(displayObject:DisplayObject):void
+		{
+			_composedLines.push(displayObject);
+		}
+		
+		// TODO FOR ARGO
+		private var _composeRecycledInPlaceLines:int;
+		private var _composePushedLines:int;
+		private function populateAndRecycleComposedLines(object:DisplayObject):void
+		{
+			var textLine:TextLine = object as TextLine;
+			if (textLine)
+			{
+				CONFIG::debug { assert(_composePushedLines >= _composedLines.length || _composedLines[_composePushedLines] == textLine,"mismatched recycled textline"); }
+				if (_composePushedLines >= _composedLines.length)
+					_composedLines.push(textLine);
+			}
+			else	// this is the background color and goes at the head of the list
+				_composedLines.splice(0,0,object);
+			_composePushedLines++;
+		}		
+		
+		/** @private return the current format hash */
+		tlf_internal function formatHash():uint
+		{
+			if (_hostFormatHash === undefined)
+			{
+				if (_hostFormat == null)
+					_hostFormatHash = 0;
+				else
+				{	
+					var hash:uint = 0;
+					for each (var prop:Property in TextLayoutFormat.description)
+					{
+						var val:Object = _hostFormat[prop.name];
+						if (val)
+							hash = prop.hash(val,hash);
+					}
+					_hostFormatHash = hash;
+				}
+			}
+
+			return _hostFormatHash;
+		}
+		
+		/** @private Cache of emptyFormat bounds */
+		static tlf_internal var _emptyFormatCache:Dictionary = new Dictionary();
+		
+		/** @private lookup bounds for the zero length factory optimization. */
+		tlf_internal function lookupZeroLengthTextBounds():Rectangle
+		{
+			if (_sourceState != SOURCE_STRING || _text.length != 0)
+				return null;
+				
+			var hash:uint = formatHash();
+			
+			var ref:WeakRef = _emptyFormatCache[hash];
+			if (ref == null)
+				return null;
+				
+			var cachedObject:Object = ref.get();
+			
+			if (cachedObject == null)
+				return null;
+				
+			return TextLayoutFormat.isEqual(_hostFormat,cachedObject.format) ? cachedObject.bounds : null;
+		}
+		
+		/** Composes the container text; calls either the factory or <code>updateAllControllers()</code>.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function compose():void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				_textFlow.flowComposer.compose();
+			else if (_damaged)
+			{
+				if (_sourceState == SOURCE_TEXTFLOW && _textFlow.mustUseComposer())
+					convertToTextFlowWithComposer();
+				else
+				{
+					var bounds:Rectangle = lookupZeroLengthTextBounds();
+					if (bounds)
+					{
+						clearComposedLines();
+					}
+					else
+					{
+						var callback:Function;
+						if (Configuration.playerEnablesArgoFeatures)
+						{
+							// if the first thing in the array is not a TextLine its the background color from the last compose - remove it
+							var firstObj:Object = _composedLines[0];
+							if (firstObj && !(firstObj is TextLine))
+								_composedLines.splice(0,1);
+							_composeRecycledInPlaceLines = 0;
+							_composePushedLines = 0;
+							callback = populateAndRecycleComposedLines;
+						}
+						else
+						{
+							clearComposedLines();
+							callback = populateComposedLines;
+						}
+	
+						var inputManagerFactory:TextLineFactoryBase = (_sourceState == SOURCE_STRING) ? inputManagerStringFactory(_config) : _inputManagerTextFlowFactory;
+						inputManagerFactory.verticalScrollPolicy = _verticalScrollPolicy;
+						inputManagerFactory.horizontalScrollPolicy = _horizontalScrollPolicy;
+						inputManagerFactory.compositionBounds = new Rectangle(0,0,_compositionWidth,_compositionHeight);
+						inputManagerFactory.swfContext = Configuration.playerEnablesArgoFeatures ? this : _swfContext;
+							
+						if (_sourceState == SOURCE_STRING)
+						{
+							var stringFactory:StringTextLineFactory = inputManagerFactory as StringTextLineFactory;
+							// potential bug - here we use the format as textFlow.format but in the TextFlow case it is the hostFormat
+							if (!TextLayoutFormat.isEqual(stringFactory.textFlowFormat,_hostFormat))
+								stringFactory.textFlowFormat = _hostFormat;
+							stringFactory.text = _text;
+							stringFactory.createTextLines(callback);
+						}
+						else
+							_inputManagerTextFlowFactory.createTextLines(callback,_textFlow);
+							
+						if (Configuration.playerEnablesArgoFeatures)
+							_composedLines.length = _composePushedLines;
+
+						bounds = inputManagerFactory.getContentBounds();
+						
+						if (_sourceState == SOURCE_STRING && _text.length == 0)
+						{
+							var obj:Object = new Object();
+							obj.format = _hostFormat;
+							obj.bounds = bounds.clone();
+							
+							_emptyFormatCache[formatHash()] = new WeakRef(obj);
+						}
+					}
+					
+					_contentLeft   = bounds.x;
+					_contentTop    = bounds.y;
+					_contentWidth  = bounds.width;
+					_contentHeight = bounds.height;
+					_damaged = false;
+					
+					// generate a compositionComplete event.  Note that the last composed position isn't known
+					if (hasEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE))
+						dispatchEvent(new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE,false,false,_textFlow,0,-1));						
+				}
+				_needsRedraw = true;
+			}
+
+		}
+		
+		/** Updates the display; calls either the factory or updateAllControllers().
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function updateContainer():void
+		{
+			compose();
+
+			if (_composeState == COMPOSE_COMPOSER)
+				_textFlow.flowComposer.updateAllControllers();
+			else if (_needsRedraw)
+			{
+				var textObject:DisplayObject; 	// scratch - TextLines and background shapes
+				if (Configuration.playerEnablesArgoFeatures)
+				{
+					// if the first child in the container is a Shape - its the background color - lose it
+					if (_container.numChildren != 0)
+					{
+						textObject = _container.getChildAt(0);
+						if (textObject && !(textObject is TextLine))
+							_container.removeChildAt(0);
+					}
+						
+					// if the first child in _composedLines is a shape push it at the head of the container
+					textObject = _composedLines[0];
+					if (textObject && !(textObject is TextLine))
+						_container.addChildAt(textObject,0);
+						
+					// expect the leading lines are reused
+					while (_container.numChildren < _composedLines.length)
+						_container.addChild(_composedLines[_container.numChildren]);
+					// recycle any trailing lines
+					while (_container.numChildren > _composedLines.length)
+					{
+						var textLine:TextLine = _container.getChildAt(_composedLines.length) as TextLine;
+						_container.removeChildAt(_composedLines.length);
+						if (textLine)
+						{
+							// lines were rebroken but aren't being displayed
+							if (textLine.validity == TextLineValidity.VALID)
+								textLine.textBlock.releaseLines(textLine,textLine.textBlock.lastLine);
+							textLine.userData = null;
+							TextLineRecycler.addLineForReuse(textLine);
+						}
+					}
+				}
+				else
+				{
+					clearContainerChildren(false);
+					
+					for each (textObject in _composedLines)
+						_container.addChild(textObject);
+						
+					clearComposedLines();
+				}
+									
+				updateBackgroundAndVisibleRectangle();
+				
+				if (_handlersState == HANDLERS_NOTADDED)
+					addActivationEventListeners();
+
+				// generate a updateComplete event.  Note that the controller isn't known
+				if (hasEventListener(UpdateCompleteEvent.UPDATE_COMPLETE))
+					dispatchEvent(new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE,false,false,null));	
+					
+				_needsRedraw = false;
+			}
+		}
+		
+		/** @private */
+		private function updateBackgroundAndVisibleRectangle() :void
+		{
+			drawBackgroundAndSetScrollRect(0,0);
+		}
+		
+		private function addActivationEventListeners():void
+		{	
+			var newState:int =  HANDLERS_NONE;
+			
+			if (_editingMode != EditingMode.READ_ONLY && _composeState == COMPOSE_FACTORY)
+				newState = _handlersState == HANDLERS_NOTADDED ? HANDLERS_CREATION : HANDLERS_ACTIVE;
+			
+			if (newState == _handlersState)
+				return;
+			
+			removeActivationEventListeners();
+				
+			if (newState == HANDLERS_CREATION)
+			{
+				_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
+				_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+			}
+			else if (newState == HANDLERS_ACTIVE)
+			{
+				_container.addEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
+				_container.addEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+				_container.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+				_container.addEventListener(MouseEvent.MOUSE_OUT,  mouseOutHandler);
+				_container.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
+			//	_container.addEventListener(IMEEvent.IME_START_COMPOSITION, imeStartCompositionHandler);
+			// attach by literal event name to avoid Argo dependency
+				_container.addEventListener("imeStartComposition", imeStartCompositionHandler);
+				_container.contextMenu = getContextMenu();
+				if (_container.contextMenu)
+		            _container.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
+		            
+		        _container.addEventListener(Event.SELECT_ALL, editHandler);
+			}
+			
+			_handlersState = newState;
+		}
+		
+		// The ContextMenu to be used.  The idea is that this is undefined until createContextMenu is called and then 
+		// createContextMenu is only called once and the result is shared with the ContainerController when it gets created
+		private var _contextMenu:*;
+		
+		/** @private  Returns the already created contextMenu.  If not created yet create it.  */
+		tlf_internal function getContextMenu():ContextMenu
+		{
+			if (_contextMenu === undefined)
+				_contextMenu = createContextMenu();
+			return _contextMenu;
+		}
+
+		private function removeActivationEventListeners():void
+		{
+			if (_handlersState == HANDLERS_CREATION)
+			{
+				_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
+				_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+			}
+			else if (_handlersState == HANDLERS_ACTIVE)
+			{
+				_container.removeEventListener(FocusEvent.FOCUS_IN, requiredFocusInHandler);				
+				_container.removeEventListener(MouseEvent.MOUSE_OVER, requiredMouseOverHandler);
+				_container.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
+				_container.removeEventListener(MouseEvent.MOUSE_OUT,  mouseOutHandler);
+				_container.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
+			//	_container.removeEventListener(IMEEvent.IME_START_COMPOSITION, imeStartCompositionHandler);
+			// detach by literal event name to avoid Argo dependency
+				_container.removeEventListener("imeStartComposition", imeStartCompositionHandler);
+				if (_container.contextMenu)	
+				{
+	            	_container.contextMenu.removeEventListener(ContextMenuEvent.MENU_SELECT, menuSelectHandler);
+					_container.contextMenu = null;
+				}
+		        _container.removeEventListener(Event.SELECT_ALL, editHandler);
+			}
+			_handlersState = HANDLERS_NOTADDED;
+		}
+		
+		private function addTextFlowListeners():void
+		{
+			for each (var event:String in eventList)			
+				_textFlow.addEventListener(event,dispatchEvent);
+		}
+		
+		private function removeTextFlowListeners():void
+		{
+			for each (var event:String in eventList)			
+				_textFlow.removeEventListener(event,dispatchEvent);
+			_handlersState = HANDLERS_NONE;
+		}
+		
+		/**
+		 * @copy flash.events.IEventDispatcher#dispatchEvent()
+		 * @private
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */
+		public override function dispatchEvent(event:Event):Boolean
+		{
+			if (event.type == DamageEvent.DAMAGE)
+			{
+				_textDamaged = true;
+				if (_composeState == COMPOSE_FACTORY)
+					_damaged = true;
+			}
+			else if (event.type == FlowOperationEvent.FLOW_OPERATION_BEGIN)
+			{
+				if (_container.mouseChildren == false)
+					_container.mouseChildren = true;
+			}
+			var result:Boolean = super.dispatchEvent(event);
+			if (!result)
+				event.preventDefault();
+			return result;
+		}
+		
+		private function clearContainerChildren(recycle:Boolean):void
+		{
+			while(_container.numChildren)
+			{
+				var textLine:TextLine = _container.getChildAt(0) as TextLine;
+				_container.removeChildAt(0);
+				if (textLine)
+				{
+					// releasing all textLines so release each still connected textBlock
+					if (textLine.validity != TextLineValidity.INVALID && textLine.validity != TextLineValidity.STATIC)
+					{
+						var textBlock:TextBlock = textLine.textBlock;
+						CONFIG::debug { Debugging.traceFTECall(null,textBlock,"releaseLines",textBlock.firstLine, textBlock.lastLine); }	
+						textBlock.releaseLines(textBlock.firstLine,textBlock.lastLine);
+					}					
+					if (recycle)
+					{
+						textLine.userData = null;	// clear any userData
+						TextLineRecycler.addLineForReuse(textLine);
+					}
+				}
+			}
+		}
+		
+		private function convertToTextFlow():void
+		{
+			CONFIG::debug { assert(_sourceState != SOURCE_TEXTFLOW,"bad call to convertToTextFlow"); }
+									
+			_textFlow = new TextFlow(_config);
+			_textFlow.hostFormat = _hostFormat;
+			if(_swfContext)
+			{
+				_textFlow.flowComposer.swfContext = _swfContext;
+			}
+	
+			var p:ParagraphElement = new ParagraphElement();
+			_textFlow.addChild(p)
+			var s:SpanElement = new SpanElement();
+			s.text = _text;
+			p.addChild(s);
+			_sourceState = SOURCE_TEXTFLOW;
+			addTextFlowListeners();			
+		}
+				
+		/** @private */
+		tlf_internal function convertToTextFlowWithComposer():void
+		{
+			removeActivationEventListeners();
+			
+			if (_sourceState != SOURCE_TEXTFLOW)
+				convertToTextFlow();
+			
+			if (_composeState != COMPOSE_COMPOSER)
+			{
+				clearContainerChildren(true);
+				clearComposedLines();
+				var controller:TMContainerController = new TMContainerController(_container,_compositionWidth,_compositionHeight,this);
+				_textFlow.flowComposer = new StandardFlowComposer();
+				_textFlow.flowComposer.addController(controller);
+				_textFlow.flowComposer.swfContext = _swfContext;
+				_composeState = COMPOSE_COMPOSER;
+				
+				invalidateInteractionManager();
+				updateContainer();
+			}
+		}
+		
+		private function get effectiveBlockProgression():String
+		{
+			if (_textFlow)
+				return _textFlow.computedFormat.blockProgression;
+			return _hostFormat && _hostFormat.blockProgression && _hostFormat.blockProgression != FormatValue.INHERIT ? _hostFormat.blockProgression : BlockProgression.TB;
+		}
+		
+		/* CONFIG::debug private static function doTrace(msg:String):void
+		{ trace(msg); } */
+		
+		private function removeIBeamCursor():void
+		{
+			if (_ibeamCursorSet)
+			{
+				Mouse.cursor = MouseCursor.AUTO;
+				_ibeamCursorSet = false;
+			}
+		}
+		
+		private var _hasScrollRect:Boolean = false;
+		
+		/** 
+		 * Specifies whether this container has attached a ScrollRect object. Value is <code>true</code>
+		 * or <code>false</code>. A display object is cropped to the size defined by the scroll rectangle, and 
+		 * it scrolls within the rectangle when you change the x and y properties of the scrollRect object. 
+		 *
+		 * <p>This property enables a client to test for a ScrollRect object without accessing 
+		 * the DisplayObject.scrollRect property, which can have side effects in some cases.</p> 
+		 *
+		 * @return true if the controller has attached a ScrollRect instance.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 *
+		 * @see #drawBackgroundAndSetScrollRect 
+		 */
+		private function get hasScrollRect():Boolean
+		{ return _hasScrollRect; }
+		private function set hasScrollRect(value:Boolean):void
+		{ _hasScrollRect = value; }
+		
+		/**   
+		 * Returns <code>true</code> if it has filled in the container's scrollRect property.  
+		 * This method enables you to test whether <code>scrollRect</code> is set without actually accessing the <code>scrollRect</code> property 
+		 * which can possibly create a  performance issue. 
+		 * <p>Override this method to draw a background or a border.  Overriding this method can be tricky as the scrollRect <bold>must</bold> 
+		 * be set as specified.</p>
+		 * 
+		 * @param scrollX The starting horizontal position of the scroll rectangle.
+		 * @param scrollY The starting vertical position of the scroll rectangle.
+		 * 
+		 * @return 	<code>true</code> if it has created the <code>scrollRect</code> object.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */
+		public function drawBackgroundAndSetScrollRect(scrollX:Number,scrollY:Number):Boolean
+		{
+			var cont:Sprite = this.container;
+
+ 			var contentWidth:Number;
+			var contentHeight:Number;
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				contentWidth = _contentWidth;
+				contentHeight = _contentHeight;
+			}
+			else
+			{
+				var controller:ContainerController = getController();
+				contentWidth = controller.contentWidth;
+				contentHeight = controller.contentHeight
+			}
+			var width:Number;
+			if (isNaN(compositionWidth))
+			{
+				var contentLeft:Number = (_composeState == COMPOSE_FACTORY) ? _contentLeft : controller.contentLeft;
+				width = contentLeft + contentWidth;
+			}
+			else
+				width = compositionWidth;
+			var height:Number;
+			if (isNaN(compositionHeight))
+			{ 
+				var contentTop:Number = (_composeState == COMPOSE_FACTORY) ? _contentTop : controller.contentTop;
+				height = contentTop+contentHeight;
+			}
+			else
+				height = compositionHeight;
+			
+			if (scrollX == 0 && scrollY == 0 && contentWidth <= width && contentHeight <= height)
+			{
+				// skip the scrollRect
+				if (_hasScrollRect)
+				{
+					cont.scrollRect = null;
+					_hasScrollRect = false;					
+				}
+			}
+			else
+			{
+				cont.scrollRect = new Rectangle(scrollX, scrollY, width, height);
+				_hasScrollRect = true;
+				
+				// adjust to the values actually in the scrollRect
+				scrollX = cont.scrollRect.x;
+				scrollY = cont.scrollRect.y;
+				width = cont.scrollRect.width;
+				height = cont.scrollRect.height;
+			}
+			
+	        // NOTE: must draw a background for interaction support - even it if is 100% transparent
+	        var s:Sprite = cont as Sprite;
+	        if (s)
+	        {
+				s.graphics.clear();
+				s.graphics.beginFill(0, 0); 
+		       	s.graphics.drawRect(scrollX,scrollY,width,height);
+		        s.graphics.endFill();
+		    }
+	
+	        return _hasScrollRect;
+		}
+		
+		/** Returns the focusedSelectionFormat - by default get it from the configuration.
+		 * This can be overridden in the subclass to supply a different SelectionFormat
+		 */
+		protected function getFocusedSelectionFormat():SelectionFormat
+		{
+			return _config.focusedSelectionFormat;
+		}
+		
+		/** Returns the inactiveSelectionFormat - by default get it from the configuration 
+		 * This can be overridden in the subclass to supply a different SelectionFormat
+		 */
+		protected function getInactiveSelectionFormat():SelectionFormat
+		{
+			return _config.inactiveSelectionFormat;
+		}
+		
+		/** Returns the unfocusedSelectionFormat - by default get it from the configuration 
+		 * You can override this method in the subclass to supply a different SelectionFormat.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		protected function getUnfocusedSelectionFormat():SelectionFormat
+		{
+			return _config.unfocusedSelectionFormat;
+		}
+		
+		/** 
+		 * Returns the undo manager to use. By default, creates a unique undo manager. 
+		 * You can override this method in the subclass if you want to customize the undo manager
+		 * (for example, to use a shared undo manager for multiple TextContainerManager instances).
+		 *
+		 * @return 	new IUndoManager instance.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+	 	 */
+		 
+		protected function getUndoManager():IUndoManager
+		{
+			return new UndoManager();
+		}
+						
+		/** Creates a ContextMenu for the TextContainerManager. Use the methods of the ContextMenu 
+		 *  class to add items to the menu. 
+		 * <p>You can override this method to define a custom context menu.</p>
+		 *
+		 * @return 	the created context menu.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 * @see flash.ui.ContextMenu ContextMenu
+		 */
+		protected function createContextMenu():ContextMenu
+		{
+			return ContainerController.createDefaultContextMenu();
+		}
+		/** @copy flashx.textLayout.container.ContainerController#editHandler()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+ 		 *
+ 		 * @see flash.events.Event Event
+		 */	
+		public function editHandler(event:Event):void
+		{
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				convertToTextFlowWithComposer();
+				getController().editHandler(event);
+				_textFlow.interactionManager.setFocus();
+			}
+			else
+				getController().editHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#keyDownHandler() 
+		*
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.KeyboardEvent#KEY_DOWN KeyboardEvent.KEY_DOWN
+		*/	
+		public function keyDownHandler(event:KeyboardEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().keyDownHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#keyUpHandler().
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.KeyboardEvent#KEY_UP KeyboardEvent.KEY_UP
+		*/	
+		public function keyUpHandler(event:KeyboardEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().keyUpHandler(event);
+		}
+
+		/** @copy flashx.textLayout.container.ContainerController#keyFocusChangeHandler().
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * 	@param	event	the FocusChange event
+		 */	
+		public function keyFocusChangeHandler(event:FocusEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().keyFocusChangeHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#textInputHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.TextEvent#TEXT_INPUT TextEvent.TEXT_INPUT
+		*/
+		public function textInputHandler(event:TextEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().textInputHandler(event);
+		}
+
+		/** Processes the <code>IME_START_COMPOSITION</code> event when the client manages events.
+		 *
+		 * @param event  The IMEEvent object.
+		 *
+		 * @playerversion Flash 10.1
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 *
+		 * @see flash.events.IMEEvent#IME_START_COMPOSITION IMEEvent.IME_START_COMPOSITION
+		 */
+		public function imeStartCompositionHandler(event:IMEEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().imeStartCompositionHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#mouseDownHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#MOUSE_DOWN MouseEvent.MOUSE_DOWN
+		*/	
+		public function mouseDownHandler(event:MouseEvent):void
+		{
+			// doTrace("IM:mouseDownHandler");
+			// before the mouseDown do a mouseOver
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				CONFIG::debug { assert(event.currentTarget == this.container,"TextContainerManager:mouseDownHandler - unexpected currentTarget"); }
+				convertToTextFlowWithComposer();
+				getController().requiredFocusInHandler(null);
+				getController().requiredMouseOverHandler(event.target != container ? new RemappedMouseEvent(event) : event);
+				if (_hasFocus)
+					getController().requiredFocusInHandler(null);
+				getController().requiredMouseDownHandler(event);
+			}
+			else
+				getController().mouseDownHandler(event);
+		}
+
+		/** @copy flashx.textLayout.container.ContainerController#mouseMoveHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#MOUSE_MOVE MouseEvent.MOUSE_MOVE
+		*/	
+		public function mouseMoveHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseMoveHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#mouseUpHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#MOUSE_UP MouseEvent.MOUSE_UP
+		*/	
+		public function mouseUpHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseUpHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#mouseDoubleClickHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#DOUBLE_CLICK MouseEvent.DOUBLE_CLICK
+		*/	
+		public function mouseDoubleClickHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseDoubleClickHandler(event);
+		}
+
+		/** @private Process a mouseOver event.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/			
+		tlf_internal final function requiredMouseOverHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_FACTORY)
+				mouseOverHandler(event);
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().requiredMouseOverHandler(event);
+		}
+		
+
+		/** Process a mouseOver event.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#MOUSE_OVER MouseEvent.MOUSE_OVER
+		*/			
+		public function mouseOverHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseOverHandler(event);
+			else
+			{
+				// doTrace("IM:mouseOverHandler");
+				if (effectiveBlockProgression != BlockProgression.RL)
+				{
+					Mouse.cursor = MouseCursor.IBEAM;
+					_ibeamCursorSet = true;
+				}	
+				addActivationEventListeners();
+			}
+		}
+		/** @copy flashx.textLayout.container.ContainerController#mouseOutHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.MouseEvent#MOUSE_OUT MouseEvent.MOUSE_OUT
+		*/					
+		public function mouseOutHandler(event:MouseEvent):void
+		{
+			// doTrace("IM:mouseOutHandler");
+			if (_composeState == COMPOSE_FACTORY)
+				removeIBeamCursor();
+			else
+				getController().mouseOutHandler(event);
+		}		
+		/** @copy flashx.textLayout.container.ContainerController#focusInHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.FocusEvent#FOCUS_IN FocusEvent.FOCUS_IN
+		*/
+
+		
+		/** Process a focusIn event.
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/
+		public function focusInHandler(event:FocusEvent):void
+		{
+			_hasFocus = true;
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().focusInHandler(event);
+		}
+		
+		/** @private hook to get at requiredFocusOutHandler as needed */
+		tlf_internal function requiredFocusOutHandler(event:FocusEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().requiredFocusOutHandler(event);
+		}
+		/** @copy flashx.textLayout.container.ContainerController#focusOutHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.FocusEvent#FOCUS_OUT FocusEvent.FOCUS_OUT
+		*/
+		public function focusOutHandler(event:FocusEvent):void
+		{
+			_hasFocus = false;
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().focusOutHandler(event);
+		}
+
+		/** @copy flashx.textLayout.container.ContainerController#activateHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.Event#ACTIVATE Event.ACTIVATE
+		*/				
+		public function activateHandler(event:Event):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().activateHandler(event);
+		}		
+		/** @copy flashx.textLayout.container.ContainerController#deactivateHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		* @see flash.events.Event#DEACTIVATE Event.DEACTIVATE
+		*/				
+		public function deactivateHandler(event:Event):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().deactivateHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#focusChangeHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		*
+ 		* @see flash.events.FocusEvent#KEY_FOCUS_CHANGE FocusEvent.KEY_FOCUS_CHANGE
+		* @see flash.events.FocusEvent#MOUSE_FOCUS_CHANGE FocusEvent.MOUSE_FOCUS_CHANGE
+		*/				
+		public function focusChangeHandler(event:FocusEvent):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().focusChangeHandler(event);
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#menuSelectHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		*
+ 		* @see flash.events.ContextMenuEvent#MENU_SELECT ContextMenuEvent.MENU_SELECT
+		*/				
+		public function menuSelectHandler(event:ContextMenuEvent):void
+		{
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				// there is no selection
+				var cbItems:ContextMenuClipboardItems = _container.contextMenu.clipboardItems
+				cbItems.selectAll = _editingMode != EditingMode.READ_ONLY;
+				cbItems.clear = false;
+				cbItems.copy = false;
+				cbItems.cut = false;
+				cbItems.paste = false;
+			}
+			else
+				getController().menuSelectHandler(event);			
+		}
+		
+		/** @copy flashx.textLayout.container.ContainerController#mouseWheelHandler()
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+ 		*
+ 		* @see flash.events.MouseEvent#MOUSE_WHEEL MouseEvent.MOUSE_WHEEL
+		*/				
+		public function mouseWheelHandler(event:MouseEvent):void
+		{
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				convertToTextFlowWithComposer();
+				getController().requiredMouseOverHandler(event);
+			}
+			getController().mouseWheelHandler(event);
+		}
+
+		
+		/** @private required FocusIn handler.  Clients override focusInHandler
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 		* @langversion 3.0
+		*/
+		tlf_internal final function requiredFocusInHandler(event:FocusEvent):void
+		{			
+			// doTrace("IM:focusInHandler");
+			if (_composeState == COMPOSE_FACTORY)
+			{
+				addActivationEventListeners();
+				focusInHandler(event);
+			}			
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().requiredFocusInHandler(event);
+		}
+		
+		/** 
+		 * Called to request clients to begin the forwarding of mouseup and mousemove events from outside a security sandbox.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function beginMouseCapture():void
+		{ }
+		/** 
+		 * Called to inform clients that the the forwarding of mouseup and mousemove events from outside a security sandbox is no longer needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function endMouseCapture():void
+		{ }
+		/** Client call to forward a mouseUp event from outside a security sandbox.  Coordinates of the mouse up are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */
+		public function mouseUpSomewhere(e:Event):void
+		{
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseUpSomewhere(e);
+		}
+		/** Client call to forward a mouseMove event from outside a security sandbox.  Coordinates of the mouse move are not needed.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 *
+		 */		
+		public function mouseMoveSomewhere(e:Event):void
+		{ 
+			if (_composeState == COMPOSE_COMPOSER)
+				getController().mouseUpSomewhere(e);
+		}
+		
+	}
+	
+}
+
+import flash.display.DisplayObject;
+import flash.display.DisplayObjectContainer;
+import flash.display.Sprite;
+import flash.events.Event;
+import flash.geom.Rectangle;
+import flash.geom.Point;
+
+import flashx.textLayout.container.ContainerController;
+import flashx.textLayout.container.ScrollPolicy;
+import flashx.textLayout.container.TextContainerManager;
+import flashx.textLayout.edit.IInteractionEventHandler;
+import flashx.textLayout.formats.BlockProgression;
+import flashx.textLayout.tlf_internal;
+import flash.events.MouseEvent;
+import flashx.textLayout.formats.BackgroundColor;
+import flash.ui.ContextMenu;
+
+use namespace tlf_internal;
+
+class TMContainerController extends ContainerController
+{
+	private var _inputManager:TextContainerManager;
+	
+	public function TMContainerController(container:Sprite, compositionWidth:Number, compositionHeight:Number, tm:TextContainerManager)
+	{
+		super(container,compositionWidth,compositionHeight);
+		_inputManager = tm;
+		verticalScrollPolicy = tm.verticalScrollPolicy;
+		horizontalScrollPolicy = tm.horizontalScrollPolicy;
+	}
+
+	/** Reroute to the TextContainerManger's override.  Reuse the one that's already been created. */
+	protected override function createContextMenu():ContextMenu
+	{ return _inputManager.getContextMenu(); }
+
+	/** @private */
+	protected override function get attachTransparentBackground():Boolean
+	{ return false; }
+	
+	/** @private */
+	tlf_internal function doUpdateVisibleRectangle():void
+	{ updateVisibleRectangle(); }
+	
+	/** @private. Override clones and enhances parent class functionality. */
+	protected override function updateVisibleRectangle() :void
+	{
+		var xpos:Number;
+		var ypos:Number;
+		// see the adjustLines boolean in ContainerController.fillShapeChildren - this logic clones that and allows for skipping the scrollRect
+		xpos = effectiveBlockProgression == BlockProgression.RL && (verticalScrollPolicy != ScrollPolicy.OFF || horizontalScrollPolicy != ScrollPolicy.OFF) ? horizontalScrollPosition - compositionWidth : horizontalScrollPosition;
+		ypos = verticalScrollPosition;
+			
+		_hasScrollRect = _inputManager.drawBackgroundAndSetScrollRect(xpos,ypos);
+	}
+		
+	/** @private */
+	tlf_internal override function getInteractionHandler():IInteractionEventHandler
+	{ return _inputManager; }
+
+}
+
+// remap the mouse event for processing inside TLF.  This is just the initial click.  Make it as if the event was on the container and not the textline
+class RemappedMouseEvent extends MouseEvent
+{
+	private var _event:MouseEvent;
+	
+	public function RemappedMouseEvent(event:MouseEvent,cloning:Boolean = false)
+	{
+		var containerPoint:Point;
+		if (!cloning)
+		{
+			containerPoint = DisplayObject(event.target).localToGlobal(new Point(event.localX, event.localY));
+			containerPoint = DisplayObject(event.currentTarget).globalToLocal(containerPoint);
+		}
+		else
+			containerPoint = new Point();
+
+		/* event.commandKey,event.controlKey,event.clickCount are also supported in AIR.  IMHO they are a nonissue for the initial click */
+		super(event.type,event.bubbles,event.cancelable,containerPoint.x,containerPoint.y,event.relatedObject,event.ctrlKey,event.altKey,event.shiftKey,event.buttonDown,event.delta);
+		
+		_event = event;
+	}
+
+	// override methods/getters for things we couldn't set in the base class	
+
+	public override function get target():Object
+	{ return _event.currentTarget; }
+	
+	public override function get currentTarget():Object
+	{ return _event.currentTarget; }
+	
+	public override function get eventPhase():uint
+	{ return _event.eventPhase; }
+	
+	public override function get isRelatedObjectInaccessible():Boolean
+	{ return _event.isRelatedObjectInaccessible; }
+	
+	public override function get stageX():Number
+	{ return _event.stageX; }
+	
+	public override function get stageY():Number
+	{ return _event.stageY; }
+	
+	public override function clone():Event
+	{ 
+		var rslt:RemappedMouseEvent = new RemappedMouseEvent(_event,true); 
+		rslt.localX = localX;
+		rslt.localY = localY;
+		return rslt;
+	}
+	
+	public override function updateAfterEvent():void
+	{ _event.updateAfterEvent(); }
+	
+	public override function isDefaultPrevented():Boolean
+	{ return _event.isDefaultPrevented(); }
+	
+	public override function preventDefault():void
+	{ _event.preventDefault(); }
+	
+	public override function stopImmediatePropagation():void
+	{ _event.stopImmediatePropagation(); }
+	
+	public override function stopPropagation():void
+	{ _event.stopPropagation(); }
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/EditManager.as b/textLayout_edit/src/flashx/textLayout/edit/EditManager.as
new file mode 100755
index 0000000..74ddd9d
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/EditManager.as
@@ -0,0 +1,1549 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.display.DisplayObjectContainer;
+	import flash.errors.IllegalOperationError;
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.IMEEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.TextEvent;
+	import flash.system.Capabilities;
+	import flash.ui.Keyboard;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.events.FlowOperationEvent;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.operations.ApplyElementIDOperation;
+	import flashx.textLayout.operations.ApplyElementStyleNameOperation;
+	import flashx.textLayout.operations.ApplyFormatOperation;
+	import flashx.textLayout.operations.ApplyFormatToElementOperation;
+	import flashx.textLayout.operations.ApplyLinkOperation;
+	import flashx.textLayout.operations.ApplyTCYOperation;
+	import flashx.textLayout.operations.ClearFormatOnElementOperation;
+	import flashx.textLayout.operations.ClearFormatOperation;
+	import flashx.textLayout.operations.CompositeOperation;
+	import flashx.textLayout.operations.CutOperation;
+	import flashx.textLayout.operations.DeleteTextOperation;
+	import flashx.textLayout.operations.FlowOperation;
+	import flashx.textLayout.operations.InsertInlineGraphicOperation;
+	import flashx.textLayout.operations.InsertTextOperation;
+	import flashx.textLayout.operations.ModifyInlineGraphicOperation;
+	import flashx.textLayout.operations.PasteOperation;
+	import flashx.textLayout.operations.RedoOperation;
+	import flashx.textLayout.operations.SplitParagraphOperation;
+	import flashx.textLayout.operations.UndoOperation;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.CharacterUtil;
+	import flashx.textLayout.utils.NavigationUtil;
+	import flashx.undo.IOperation;
+	import flashx.undo.IUndoManager;
+		
+	use namespace tlf_internal;
+	
+	/** 
+	 * The EditManager class manages editing changes to a TextFlow. 
+	 * 
+	 * <p>To enable text flow editing, assign an EditManager object to the <code>interactionManager</code> 
+	 * property of the TextFlow object. The edit manager handles changes to the text (such as insertions, 
+	 * deletions, and format changes). Changes are reversible if the edit manager has an undo manager. The edit
+	 * manager triggers the recomposition and display of the text flow, as necessary.</p>
+	 *
+	 * <p>The EditManager class supports the following keyboard shortcuts:</p>
+	 * 
+	 * <table class="innertable" width="100%">
+	 *      <tr><th>Keys</th><th>Result</th></tr>
+	 *      <tr><td>ctrl-z</td><td>undo</td></tr>					
+	 * 	<tr><td>ctrl-y</td><td>redo</td></tr>					
+	 * 	<tr><td>ctrl-backspace</td><td>deletePreviousWord</td></tr>					
+	 * 	<tr><td>ctrl-delete</td><td>deleteNextWord</td></tr>					
+	 * 	<tr><td>alt+delete</td><td>deleteNextWord</td></tr>					
+	 * 	<tr><td>ctrl+alt-delete</td><td>deleteNextWord</td></tr>					
+	 * 	<tr><td>ctrl-shift-hyphen</td><td>insert discretionary hyphen</td></tr>					
+	 * 	<tr><td>ctrl+backspace</td><td>deletePreviousWord</td></tr>					
+	 * 	<tr><td>alt+backspace</td><td>deletePreviousWord</td></tr>					
+	 * 	<tr><td>ctrl+alt-backspace</td><td>deletePreviousWord</td></tr>					
+	 * 	<tr><td>INSERT</td><td>toggles overWriteMode</td></tr>					
+	 * 	<tr><td>backspace</td><td>deletePreviousCharacter</td></tr>					
+	 * 	<tr><td>ENTER</td><td>if textFlow.configuration.manageEnterKey splitParagraph</td></tr>					
+	 * 	<tr><td>TAB</td><td>if textFlow.configuration.manageTabKey insert a TAB or overwrite next character with a TAB</td></tr>    
+	 * </table>
+	 *
+	 * <p><strong>Note:</strong> The following keys do not work on Windows: alt-backspace, alt-delete, ctrl+alt-backspace,
+	 * and ctrl+alt-delete. These keys do not generate an event for the runtime.</p>						
+ 	 * 
+ 	 * @see flashx.textLayout.elements.TextFlow
+ 	 * @see flashx.undo.UndoManager
+	 *
+	 * @includeExample examples\EditManager_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */			
+	public class EditManager extends SelectionManager implements IEditManager
+	{
+		 /**
+		 *  To minimize expensive recompositions during fast typing, inserts
+		 *  don't necessarily take place immediately. An insert operation that
+		 *  hasn't yet executed is held here.
+		 */
+		private var pendingInsert:InsertTextOperation;
+		
+		/** 
+		 * The object that has the ENTER_FRAME event listener attached to perform pending inserts.
+		 */
+		private var enterFrameListener:DisplayObjectContainer;
+		
+		/**
+		 *  Some operations can be undone & redone. The undoManager keeps track
+		 *  of the operations that have been done or undone so that they can be undone or
+		 *  redone.  I'm not sure if only text operations can be undone. If so, the undoManager
+		 *  should probably be moved to EditManager.
+		 */
+		private var _undoManager:flashx.undo.IUndoManager;
+		
+		private var _imeSession:IMEClient;
+		private var _imeOperationInProgress:Boolean;
+		
+		/** 
+		 * Indicates whether overwrite mode is on or off.
+		 * 
+		 * <p>If <code>true</code>, then a keystroke overwrites the character following the cursor.
+		 * If <code>false</code>, then a keystroke is inserted at the cursor location.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/		
+		public static var overwriteMode:Boolean = false;
+		
+		/** 
+		 * Creates an EditManager object.
+		 * 
+		 * <p>Assign an EditManager object to the <code>interactionManager</code> property
+		 * of a text flow to enable editing of that text flow. </p>
+		 *
+		 * <p>To enable support for undoing and redoing changes, pass an 
+		 * IUndoManager instance to the EditManager constructor. You can use
+		 * the <code>flashx.undo.UndoManager</code> class
+		 * or create a custom IUndoManager instance. Use a custom IUndoManager instance
+		 * to integrate Text Layout Framework changes with an existing
+		 * undo manager that is not an instance of the UndoManager class.
+		 * To create a custom IUndoManager instance, ensure that the class
+		 * you use to define the undo manager 
+		 * implements the IUndoManager interface.</p>
+		 * 
+		 * 
+		 * @param undo	The UndoManager for the application
+		 * 
+		 * @see flashx.textLayout.elements.TextFlow#interactionManager
+		 * @see flashx.undo.IUndoManager
+		 * 
+		 * @includeExample examples\EditManager_constructor.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function EditManager(undoManager:flashx.undo.IUndoManager = null)
+		{
+			super();
+			_undoManager = undoManager;
+		}
+
+		/**  
+		 * The IUndoManager assigned to this edit manager.
+		 * 
+		 * <p>To allow edits to be undone (and redone), pass an IUndoManager instance to the EditManager
+		 * constructor. The undo manager maintains a stack of operations that have been executed, and it can 
+		 * undo or redo individual operations. </p>
+		 * 
+		 * <p><b>Note:</b> If the TextFlow is modified directly (not via
+		 * calls to the EditManager, but directly via calls to the managed FlowElement objects), then the EditManager
+		 * clears the undo stack to prevent the stack from getting out of sync with the current state.</p>
+		 * 
+	 	 * @playerversion Flash 10
+	 	 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+	 	 */	
+		public function get undoManager():flashx.undo.IUndoManager
+		{
+			return _undoManager;
+		}
+		
+		// Backdoor provided so that IMEClient can temporarily use an undo manager to maintain the IME session state.
+		/** @private */
+		tlf_internal function setUndoManager(undoManager:flashx.undo.IUndoManager):void
+		{
+			_undoManager = undoManager;
+		}
+		
+		override public function editHandler(event:Event):void
+		{
+			super.editHandler(event);
+			switch (event.type)
+			{
+				case Event.CUT: 
+					if (activePosition != anchorPosition)
+						TextClipboard.setContents(cutTextScrap());
+					break;
+				case Event.CLEAR:
+					if(activePosition != anchorPosition)
+						deleteText(null);
+					break;
+				case Event.PASTE:
+					pasteTextScrap(TextClipboard.getContents());
+					break;
+			}
+		}
+
+		// ///////////////////////////////////
+		// keyboard methods 
+		// ///////////////////////////////////
+		
+		/** @private */
+		public override function keyDownHandler(event:KeyboardEvent):void
+		{
+			if (!hasSelection() || event.isDefaultPrevented())
+				return;
+				
+			super.keyDownHandler(event);
+			
+			if (event.ctrlKey)
+			{
+				// The player subsequently sends a text input event (which should be ignored) as listed below:
+				// CTRL/CMD+z: Only on Mac when using a pre-Argo player version
+				// CTRL/CMD+y: On all platforms (the exact char code for the text input event is platform dependent) 
+				if (!event.altKey)
+				{
+					switch(event.charCode)
+					{
+						case 122:	// small z
+							/* pre-Argo and on the mac then ignoreNextTextEvent */ 
+							if (!Configuration.versionIsAtLeast(10,1) && (Capabilities.os.search("Mac OS") > -1)) 
+								ignoreNextTextEvent = true;
+							undo();
+							event.preventDefault();
+							break;
+						case 121:	// small y
+							ignoreNextTextEvent = true;
+							redo();
+							event.preventDefault();
+							break;
+						case Keyboard.BACKSPACE:
+							if (_imeSession)
+								_imeSession.compositionAbandoned();
+							deletePreviousWord();
+							event.preventDefault();
+							break;
+					}
+					if (event.keyCode == Keyboard.DELETE)
+					{
+						if (_imeSession)
+							_imeSession.compositionAbandoned();
+						deleteNextWord();
+						event.preventDefault();
+					}
+					
+					if (event.shiftKey)
+					{
+						// detect ctrl-shift-"-" (cnd-shift-"-" on mac) and insert a DH
+						if (event.charCode == 95)
+						{
+							if (_imeSession)
+								_imeSession.compositionAbandoned();
+
+							//a discretionary hyphen is being inserted. 
+							var discretionaryHyphenString:String = String.fromCharCode(0x000000AD);
+							overwriteMode ? overwriteText(discretionaryHyphenString) : insertText(discretionaryHyphenString);
+							event.preventDefault();
+						}
+					}
+				}
+			} 
+			else if (event.altKey)
+			{
+				if (event.charCode == Keyboard.BACKSPACE)
+				{
+					deletePreviousWord();
+					event.preventDefault();
+				}
+				else if (event.keyCode == Keyboard.DELETE)
+				{
+					deleteNextWord();
+					event.preventDefault();
+				}
+			}
+			// not ctrl key or alt key
+			else if (event.keyCode == Keyboard.DELETE) //del
+			{
+				deleteNextCharacter();
+				event.preventDefault();
+			}
+			else if (event.keyCode == Keyboard.INSERT) //insert
+			{
+				overwriteMode = !overwriteMode;				
+				event.preventDefault();
+			}
+			else switch(event.charCode) {
+				case Keyboard.BACKSPACE:
+					deletePreviousCharacter();
+					event.preventDefault();
+					break;
+				case Keyboard.ENTER:
+					if (textFlow.configuration.manageEnterKey) 
+					{
+						splitParagraph();
+						event.preventDefault();
+						event.stopImmediatePropagation();
+					}
+					break;
+				case Keyboard.TAB:
+					if (textFlow.configuration.manageTabKey) 
+					{
+						overwriteMode ? overwriteText(String.fromCharCode(event.charCode)) : insertText(String.fromCharCode(event.charCode));
+						event.preventDefault();
+					}
+					break;
+			}
+		}
+		
+		/** @private */
+		public override function keyUpHandler(event:KeyboardEvent):void
+		{
+			if (!hasSelection() || event.isDefaultPrevented())
+				return;
+				
+			super.keyUpHandler(event);
+			
+			if ((textFlow.configuration.manageEnterKey && event.charCode == Keyboard.ENTER) || (textFlow.configuration.manageTabKey && event.charCode == Keyboard.TAB)) {
+				event.stopImmediatePropagation();
+			}
+		}
+		
+		/** @private */	
+		public override function keyFocusChangeHandler(event:FocusEvent):void
+		{
+			if (textFlow.configuration.manageTabKey) 
+				event.preventDefault();
+		}
+	
+		/** @private */
+		public override function textInputHandler(event:TextEvent):void
+		{
+			if (!ignoreNextTextEvent)
+			{
+				var charCode:int = event.text.charCodeAt(0);
+				// only if its a space or larger - ignore control characters here
+				if (charCode >=  32)
+					overwriteMode ? overwriteText(event.text) : insertText(event.text);
+			}
+			ignoreNextTextEvent = false;
+		}
+		
+		/** @private */
+		override public function focusOutHandler(event:FocusEvent):void
+		{
+			super.focusOutHandler(event);
+			if (_imeSession && selectionFormatState != SelectionFormatState.FOCUSED)
+				_imeSession.compositionAbandoned();
+		}
+		
+		/** @private */
+		override public function deactivateHandler(event:Event):void
+		{
+			super.deactivateHandler(event);
+			if (_imeSession)
+				_imeSession.compositionAbandoned();
+		}
+		
+		/** @private */
+		override public function imeStartCompositionHandler(event:IMEEvent):void
+		{
+			CONFIG::debug{ assert(!_imeSession, "IME session already in progress: IME not reentrant!"); }
+		//	CONFIG::debug { Debugging.traceOut("imeStartComposition event"); }
+
+			// any pending operations must be executed first, to
+			// preserve operation order.
+			flushPendingOperations();
+			
+			// Coded to avoid dependency on Argo (10.1). 
+			if (!(event["imeClient"]))
+			{
+				_imeSession = new IMEClient(this);
+				_imeOperationInProgress = false;
+				event["imeClient"] = _imeSession;
+			}
+		}
+		
+		/** @private */
+		override public function setFocus():void
+		{
+			var flowComposer:IFlowComposer = textFlow ? textFlow.flowComposer : null;
+			if (_imeSession && flowComposer && flowComposer.numControllers > 1)
+			{
+				// container with the ime start position gets the key focus
+				_imeSession.setFocus();
+
+				setSelectionFormatState(SelectionFormatState.FOCUSED);
+			}
+			else
+				super.setFocus();
+		}
+		/** @private */		
+		tlf_internal function endIMESession():void
+		{
+			_imeSession = null;
+			var flowComposer:IFlowComposer = textFlow ? textFlow.flowComposer : null;
+			if (flowComposer && flowComposer.numControllers > 1)
+				setFocus();
+		}
+		/** @private */
+		tlf_internal function beginIMEOperation():void
+		{
+			_imeOperationInProgress = true;
+			beginCompositeOperation();
+		}
+		/** @private */
+		tlf_internal function endIMEOperation():void
+		{
+			endCompositeOperation();
+			_imeOperationInProgress = false;
+		}
+
+		/** @private We track the nesting level of the doOperation, because in finalize we need to know if
+		we are at the outermost level and need to push the operation on the undo stack and redraw
+		the screen, or if we're in a nested level and need to append the operation to the next
+		level up. */
+		tlf_internal var captureLevel:int = 0;
+
+		/** 
+		  * @copy IEditManager#doOperation()
+		  * 
+		  * @includeExample examples\EditManager_doOperation.as -noswf
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+ 	 	  * @langversion 3.0
+		  */
+		public override function doOperation(operation:FlowOperation):void
+		{
+			CONFIG::debug { assert(operation.textFlow == this.textFlow,"Operation from a different TextFlow"); }
+			
+			// If we get any operation during an IME session that is not owned by the session, we cancel the IME
+			if (_imeSession && !_imeOperationInProgress)
+				_imeSession.compositionAbandoned();
+			
+			// any pending operations must be executed first, to
+			// preserve operation order.
+			flushPendingOperations();
+			
+			try
+			{
+				captureLevel++;
+				operation = doInternal(operation);
+			}
+			catch(e:Error)
+			{
+				captureLevel--;
+				throw(e);
+			}
+			captureLevel--;
+			
+			if (operation)			// don't finalize if operation was cancelled
+				finalizeDo(operation);
+		}
+
+		private function finalizeDo(op:FlowOperation):void
+		{
+			// Handle operation if we're in a beginCompositeOperation/endCompositeOperation context
+			// In this case any nested commands we do will get added to the composite operation when 
+			// they're done instead of added to the undo stack.
+			var parentOperation:CompositeOperation;
+			if (parentStack && parentStack.length > 0)
+			{
+				var parent:Object = parentStack[parentStack.length - 1];
+				if (parent.captureLevel == captureLevel)
+					parentOperation = parent.operation as CompositeOperation;
+			}
+
+	//		CONFIG::debug { assert(captureLevel == 0 || parentOperation != null, "missing parent for nested operation"); }
+			
+			if (parentOperation)
+				parentOperation.addOperation(op);
+			
+			else if (captureLevel == 0)
+			{
+				captureOperations.length = 0; 
+				if (_undoManager)
+				{
+					if (_undoManager.canUndo() && allowOperationMerge)
+					{
+						var lastOp:FlowOperation = _undoManager.peekUndo() as FlowOperation;
+						if (lastOp)
+						{
+							// Try to merge the last operation on the stack with the current
+							// operation. This may modify lastOp, or return a new operation
+							var combinedOp:FlowOperation = lastOp.merge(op);
+							if (combinedOp)
+							{
+								combinedOp.setGenerations(lastOp.beginGeneration,textFlow.generation);
+								_undoManager.popUndo();
+								op = combinedOp;
+							}
+						}
+					}
+					if (op.canUndo())
+						_undoManager.pushUndo(op);
+					allowOperationMerge = true;
+
+					// following operations are no longer redoable
+					_undoManager.clearRedo();
+				}
+
+				updateAllControllers();			
+				
+				if (hasSelection())
+				{
+					var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(activePosition);
+					if (controllerIndex >= 0)
+						textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);	
+				}
+				if (!_imeSession)
+				{	
+					var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,op,0,null);
+					textFlow.dispatchEvent(opEvent);
+				}
+			}	
+		}
+		
+		private var captureOperations:Array = [];
+
+		/** Internal guts of a dooperation - Execute a FlowOperation.  This function proceeds in steps.
+		  * <p>Step 2. Send a canceallable OperationEvent.  If cancelled this method returns immediately.</p>
+		  * If it is not cancelled, the listener may "do" other operations by calling back into the EditManager. This will result
+		  * in a nested call to do which will post additional commands to the captureOperations array.
+		  * <p>Step 3. Execute the operation.  The operation returns true or false.  false indicates no changes were made.</p>
+		  * <p>Step 7. Send a OperationEvent. </p>
+		  * The listener may "do" other operations by calling back into the EditManager. This will result
+		  * in a nested call to do which will post additional commands to the captureOperations array.
+		  * <p>Exception handling.  If the operation throws the exception is caught and the error is attached to the event dispatched
+		  * at step 7.  If the event is not cancelled the error is rethrown.</p>
+		  */
+		private function doInternal(op:FlowOperation):FlowOperation
+		{
+			CONFIG::debug { assert(op.textFlow == this.textFlow,"Operation from a different TextFlow"); }
+			
+			var captureStart:int = captureOperations.length;
+			var success:Boolean = false;
+			var opEvent:FlowOperationEvent;
+			
+			// tell any listeners about the operation
+			if (!_imeSession)
+			{
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,op,captureLevel-1,null);
+				textFlow.dispatchEvent(opEvent);
+				if (opEvent.isDefaultPrevented())
+					return null;
+				// user may replace the operation - TODO: WHAT IF SWITCH TO UNDO/REDO????
+				op = opEvent.operation;
+				if ((op is UndoOperation) || (op is RedoOperation))
+					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(op) ]));
+			}
+				
+			var opError:Error = null;
+			try
+			{
+				// begin this op after pending ops are flushed
+				CONFIG::debug 
+				{ 
+					if (captureLevel <= 1)
+						debugCheckTextFlow(); 
+				}
+				
+				// null return implies no operation was done - just discard it
+				var beforeGeneration:uint = textFlow.generation;
+				op.setGenerations(beforeGeneration,0);
+	
+				captureOperations.push(op);
+				success = op.doOperation();
+				if (success)		// operation succeeded
+				{
+					textFlow.normalize();   //force normalization at this point. Don't compose unless the captureLevel is 0
+					
+					// This has to be done after the normalize, because normalize increments the generation number
+					op.setGenerations(beforeGeneration,textFlow.generation);					
+				} 
+				else 
+				{
+					var index:int = captureOperations.indexOf(op);
+					if (index >= 0) 
+						captureOperations.splice(index, 1);
+				}
+			}
+			catch(e:Error)
+			{
+				opError = e;
+			}
+			
+			// operation completed - send event whether it succeeded or not.
+			// client can check generation number for changes
+			if (!_imeSession)
+			{
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,op,captureLevel-1,opError);
+				textFlow.dispatchEvent(opEvent);
+				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
+			}
+
+			if (opError)
+				throw (opError);
+				
+			// If we fired off any subsidiary operations, create a composite operation to hold them all
+		 	if (captureOperations.length - captureStart > 1)
+		 	{
+				op = new CompositeOperation(captureOperations.slice(captureStart));
+				op.setGenerations(FlowOperation(CompositeOperation(op).operations[0]).beginGeneration,textFlow.generation);
+				allowOperationMerge = false;
+				captureOperations.length = captureStart;		
+		 	}
+			 	
+			return success ? op : null;
+		}
+
+		/** Update the display after an operation has modified it */
+		protected function updateAllControllers():void
+		{
+			if (textFlow.flowComposer)
+				 textFlow.flowComposer.updateAllControllers(); 
+
+			selectionChanged(true, false);
+				
+			CONFIG::debug { debugCheckTextFlow(); }
+		}
+		
+		/** @private */
+		public override function flushPendingOperations():void
+		{
+			super.flushPendingOperations();
+			if (pendingInsert)
+			{
+				var pi0:InsertTextOperation = pendingInsert;
+				pendingInsert = null;
+				if (enterFrameListener)
+				{
+					enterFrameListener.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
+					enterFrameListener = null;
+				}
+				doOperation(pi0);
+			}
+		}
+
+		/** 
+		 * @copy IEditManager#undo()
+		 * @includeExample examples\EditManager_undo.as -noswf
+		 * 
+		 * @see flashx.undo.IUndoManager#undo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function undo():void
+		{
+			// Cancel out of an IME session if there is one. 
+			// Some IMEs are on all the time, and so the undo has to win over the IME, 
+			// otherwise you would never be able to undo in Korean.
+			if (_imeSession)
+				_imeSession.compositionAbandoned();
+			
+			if (undoManager)
+				undoManager.undo();
+		}
+		 			
+		/** @private */
+		public function performUndo(theop:IOperation):void
+		{
+			var operation:FlowOperation = theop as FlowOperation;
+			if ((!operation) || (operation.textFlow != textFlow)) 
+				return;			
+			// tell any listeners about the operation
+			if (!_imeSession)
+			{
+				var undoPsuedoOp:UndoOperation = new UndoOperation(operation);
+				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,undoPsuedoOp,0,null);
+				textFlow.dispatchEvent(opEvent);
+				if (opEvent.isDefaultPrevented())
+				{
+					//operation cancelled by user. Push the operation back onto the undo stack
+					undoManager.pushUndo(operation);
+					return;
+				}
+				undoPsuedoOp = opEvent.operation as UndoOperation;
+				if (!undoPsuedoOp)
+					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(opEvent.operation) ]));
+				operation = undoPsuedoOp.operation;
+			}
+					
+			if (operation.endGeneration != textFlow.generation)
+			{
+				//CONFIG::debug { trace("EditManager.undo: skipping undo due to mismatched generation numbers. textFlow",textFlow.generation,flash.utils.getQualifiedClassName(operation),operation.endGeneration); }
+				return;
+			}
+				
+			var opError:Error = null;
+			try
+			{
+				CONFIG::debug { debugCheckTextFlow(); }
+	
+				var rslt:SelectionState;
+				rslt = operation.undo();
+	
+				CONFIG::debug { assert(rslt != null,"undoable operations must return a SelectionState"); }
+				setSelectionState(rslt);
+				if (_undoManager)
+					_undoManager.pushRedo(operation);
+
+			}
+			catch(e:Error)
+			{
+				opError = e;
+			}
+				
+			// tell user its complete and give them a chance to cancel the rethrow
+			if (!_imeSession)
+			{
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,undoPsuedoOp,0,opError);
+				textFlow.dispatchEvent(opEvent);
+				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
+			}
+
+			if (opError)
+				throw (opError);
+			
+			updateAllControllers();
+			
+			// push the generation of the textFlow backwards - must be done after update which does a normalize
+			textFlow.setGeneration(operation.beginGeneration);
+			
+			if (hasSelection())
+			{
+				var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(activePosition);
+				if (controllerIndex >= 0)
+					textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);											
+			}
+			opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,undoPsuedoOp,0,null);
+			textFlow.dispatchEvent(opEvent);
+		}
+		
+		/** 
+		 * @copy IEditManager#redo()
+		 * @includeExample examples\EditManager_redo.as -noswf
+		 * 
+		 * @see flashx.undo.IUndoManager#redo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function redo():void
+		{
+			// Cancel out of an IME session if there is one. 
+			// Some IMEs are on all the time, and so the undo has to win over the IME, 
+			// otherwise you would never be able to undo in Korean.
+			if (_imeSession)
+				_imeSession.compositionAbandoned();
+			
+			if (undoManager)
+				undoManager.redo();
+		}
+		
+		/** @private */
+		public function performRedo(theop:IOperation):void
+		{
+			var opEvent:FlowOperationEvent;
+			var op:FlowOperation = theop as FlowOperation;
+			if ((!op) || (op.textFlow != textFlow)) 
+				return;
+			// tell any listeners about the operation
+			if (!_imeSession)
+			{
+				var redoPsuedoOp:RedoOperation = new RedoOperation(op);
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,redoPsuedoOp,0,null);
+				textFlow.dispatchEvent(opEvent);
+				if (opEvent.isDefaultPrevented() && _undoManager)
+				{
+					//user cancelled the event. Push the operation back onto the redo stack
+					_undoManager.pushRedo(op);
+					return;
+				}
+				redoPsuedoOp = opEvent.operation as RedoOperation;
+				if (!redoPsuedoOp)
+					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(opEvent.operation) ]));
+				op = redoPsuedoOp.operation;
+			}
+					
+			if (op.beginGeneration != textFlow.generation)
+			{
+				//CONFIG::debug { trace("EditManager.redo: skipping redo due to mismatched generation numbers."); }
+				return;
+			}
+				
+			var opError:Error = null;
+			try
+			{
+				CONFIG::debug { debugCheckTextFlow(); }					
+				var rslt:SelectionState;
+				rslt = op.redo();
+					
+				CONFIG::debug { assert(rslt != null,"redoable operations must return a SelectionState"); }
+				setSelectionState(rslt);
+				if (_undoManager)
+					_undoManager.pushUndo(op);
+
+			
+			}
+			catch(e:Error)
+			{
+				opError = e;
+			}
+				
+			// tell user its complete and give them a chance to cancel the rethrow
+			if (!_imeSession)
+			{
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,redoPsuedoOp,0,opError);
+				textFlow.dispatchEvent(opEvent);
+				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
+			}
+			if (opError)
+				throw (opError);
+			
+			updateAllControllers();
+			
+			// push the generation of the textFlow backwards - must be done after update which does a normalize
+			// set the generation of the textFlow to end of redoOp.
+			textFlow.setGeneration(op.endGeneration);
+			
+			if (hasSelection())
+			{
+				var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(activePosition);
+				if (controllerIndex >= 0)
+					textFlow.flowComposer.getControllerAt(controllerIndex).scrollToRange(activePosition,anchorPosition);						
+			}	
+			opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,op,0,null);
+			textFlow.dispatchEvent(opEvent);			
+		}
+		
+		/**
+		 * @private
+		 * Returns the editing mode (READ_ONLY, READ_SELECT, or READ_WRITE) of the EditManager.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @see flashx.textLayout.edit.EditingMode.
+		 */
+		 public override function get editingMode():String
+		 {
+		 	return EditingMode.READ_WRITE;
+		 }				 		
+		
+		// Resolve the operationState.
+		//		If the operation state is null...
+		//			Return the active selection
+		//			If there's no active selection, return null. The caller will have to check
+		//		Otherwise (operation not null)
+		//			just return it
+		/** @private */
+		tlf_internal function defaultOperationState(operationState:SelectionState = null):SelectionState
+		{
+			if (operationState)
+			{
+				// flush any pending operations and use marks to preserve the operationState positions
+				var markActive:Mark = createMark();
+				var markAnchor:Mark = createMark();
+				try
+				{
+					markActive.position = operationState.activePosition;
+					markAnchor.position = operationState.anchorPosition;
+					flushPendingOperations();
+				}
+				finally
+				{
+					removeMark(markActive);
+					removeMark(markAnchor);
+					operationState.activePosition = markActive.position;
+					operationState.anchorPosition = markAnchor.position;
+				}
+			}
+			else
+			{
+				flushPendingOperations();
+				if (hasSelection())
+				{
+					// tell the operation that the state is from the SelectionManager so it will update pending point formats
+					operationState = getSelectionState();
+					operationState.selectionManagerOperationState = true;
+				}
+			}
+			return operationState;
+		}
+
+		/** 
+		 * @copy IEditManager#splitParagraph()
+		 * @includeExample examples\EditManager_splitParagraph.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function splitParagraph(operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new SplitParagraphOperation(operationState));
+		}
+
+		/** 
+		 * @copy IEditManager#deleteText()
+		 * @includeExample examples\EditManager_deleteText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function deleteText(operationState:SelectionState = null):void
+		{
+
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new DeleteTextOperation(operationState, operationState, false /* don't allow merge when deleting by range */));				
+		}		
+		
+		/**
+		 * @copy IEditManager#deleteNextCharacter()
+		 * @includeExample examples\EditManager_deleteNextCharacter.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function deleteNextCharacter(operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			// Delete the next character if it's a caret selection, and allow adejacent delete next's to merge
+			// If it's a range selection, delete the range and disallow merge
+			var deleteOp:DeleteTextOperation;
+			if (operationState.absoluteStart == operationState.absoluteEnd)
+			{
+				var nextPosition:int = NavigationUtil.nextAtomPosition(textFlow, absoluteStart);
+				deleteOp = new DeleteTextOperation(operationState, new SelectionState(textFlow, absoluteStart, nextPosition, pointFormat), true /* allowMerge for deleteForward */);	
+			}
+			else 
+				deleteOp = new DeleteTextOperation(operationState, operationState, false /* don't allow merge when deleting by range */);			
+			doOperation(deleteOp);			
+
+		}
+
+		/** 
+		 * @copy IEditManager#deleteNextWord()
+		 * @includeExample examples\EditManager_deleteNextWord.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function deleteNextWord(operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if ((!operationState) || ((operationState.anchorPosition == operationState.activePosition) && (operationState.anchorPosition >= textFlow.textLength - 1)))
+				return;
+				
+			var nextWordSelState:SelectionState = getNextWordForDelete(operationState.absoluteStart);
+			if (nextWordSelState.anchorPosition == nextWordSelState.activePosition)
+				//nothing to delete. No operation required.
+				return;			
+
+			setSelectionState(new SelectionState(textFlow, operationState.absoluteStart, operationState.absoluteStart, new TextLayoutFormat(textFlow.findLeaf(operationState.absoluteStart).format)));
+			doOperation(new DeleteTextOperation(operationState, nextWordSelState, false));						
+		}
+
+		// Sadly, this is NOT the same as the cursor key movement - specialized for delete forward one word
+		private function getNextWordForDelete(absoluteStart:int):SelectionState
+		{
+			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+			var paraEl:ParagraphElement = leafEl.getParagraph();
+			var paraElAbsStart:int = paraEl.getAbsoluteStart();
+			
+			var nextPosition:int = -1;
+			
+			if ((absoluteStart - paraElAbsStart) >= (paraEl.textLength - 1))
+			{
+				// We're at the end of the paragraph, delete the following newline
+				nextPosition = NavigationUtil.nextAtomPosition(textFlow, absoluteStart);
+			}
+			else
+			{
+				var curPos:int = absoluteStart - paraElAbsStart;			
+				var curPosCharCode:int = paraEl.getCharCodeAtPosition(curPos);
+				var prevPosCharCode:int = -1;
+				if (curPos > 0) prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
+				var nextPosCharCode:int = paraEl.getCharCodeAtPosition(curPos + 1);
+				if (!CharacterUtil.isWhitespace(curPosCharCode) && ((curPos == 0) || ((curPos > 0) && CharacterUtil.isWhitespace(prevPosCharCode)))) {
+					nextPosition = NavigationUtil.nextWordPosition(textFlow, absoluteStart);
+				} else {
+					if (CharacterUtil.isWhitespace(curPosCharCode) && ((curPos > 0) && !CharacterUtil.isWhitespace(prevPosCharCode))) {
+						//if at beginning of space word then get through all the spaces					
+						curPos = paraEl.findNextWordBoundary(curPos);
+					}
+					nextPosition = paraElAbsStart + paraEl.findNextWordBoundary(curPos);
+				}
+			}
+			return new SelectionState(textFlow, absoluteStart, nextPosition, pointFormat);
+		}
+		
+		/**
+		 * @copy IEditManager#deletePreviousCharacter()
+		 * @includeExample examples\EditManager_deletePreviousCharacter.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function deletePreviousCharacter(operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			var deleteOp:DeleteTextOperation;
+			if (operationState.absoluteStart == operationState.absoluteEnd)
+			{	// with a caret selection, delete the previous character
+				var beginPrevious:int = NavigationUtil.previousAtomPosition(textFlow, operationState.absoluteStart);
+				deleteOp = new DeleteTextOperation(operationState, new SelectionState(textFlow, beginPrevious, operationState.absoluteStart), true /* allowMerge */);
+			}
+			else	// just delete the range
+				deleteOp = new DeleteTextOperation(operationState);
+			doOperation(deleteOp);
+		}
+		
+		/** 
+		 * @copy IEditManager#deletePreviousWord()
+		 * @includeExample examples\EditManager_deletePreviousWord.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function deletePreviousWord(operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+				
+			var prevWordSelState:SelectionState = getPreviousWordForDelete(operationState.absoluteStart);
+			if (prevWordSelState.anchorPosition == prevWordSelState.activePosition)
+				//there is nothing to delete.  No operation required
+				return;			
+				
+			setSelectionState(new SelectionState(textFlow, operationState.absoluteStart, operationState.absoluteStart, new TextLayoutFormat(textFlow.findLeaf(operationState.absoluteStart).format)));
+			doOperation(new DeleteTextOperation(operationState, prevWordSelState, false /* don't allow merge */));						
+		}		
+		
+		// Sadly, this is NOT the same as the cursor key movement - specialized for delete backward one word
+		private function getPreviousWordForDelete(absoluteStart:int):SelectionState
+		{
+			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+			var paraEl:ParagraphElement = leafEl.getParagraph();
+			var paraElAbsStart:int = paraEl.getAbsoluteStart();
+
+			if (absoluteStart == paraElAbsStart)		// at the start of the paragraph, delete the previous newline. Should insert a space after punctuation.
+			{
+				var beginPrevious:int = NavigationUtil.previousAtomPosition(textFlow, absoluteStart);
+				return new SelectionState(textFlow, beginPrevious, absoluteStart);				
+			}
+
+			var curPos:int = absoluteStart - paraElAbsStart;
+			var curPosCharCode:int = paraEl.getCharCodeAtPosition(curPos);
+			var prevPosCharCode:int = paraEl.getCharCodeAtPosition(curPos - 1);
+			var curAbsStart:int = absoluteStart;
+			
+			if (CharacterUtil.isWhitespace(curPosCharCode) && (curPos != (paraEl.textLength - 1)))
+			{
+				if (CharacterUtil.isWhitespace(prevPosCharCode)) //this will get you past the spaces
+				{
+					curPos = paraEl.findPreviousWordBoundary(curPos);
+				}
+				if (curPos > 0) {
+					curPos = paraEl.findPreviousWordBoundary(curPos); //this will get you to the beginning of the word before the space.
+					if (curPos > 0) {
+						prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
+						if (CharacterUtil.isWhitespace(prevPosCharCode)) {
+							curPos = paraEl.findPreviousWordBoundary(curPos);
+						}
+					}
+				}
+			} else { //you are here if you are not on a space
+				if (CharacterUtil.isWhitespace(prevPosCharCode))
+				{
+					curPos = paraEl.findPreviousWordBoundary(curPos); //this will get you past the spaces
+					if (curPos > 0) {
+						curPos = paraEl.findPreviousWordBoundary(curPos);
+						if (curPos > 0) {
+							prevPosCharCode = paraEl.getCharCodeAtPosition(curPos - 1);
+							if (!CharacterUtil.isWhitespace(prevPosCharCode)) {
+								curAbsStart--; //Microsoft Word insists on keeping the original space
+								               //if the ending position does not have a space.
+							}
+						}
+					}
+				} else { //just delete to the previous word boundary
+					curPos = paraEl.findPreviousWordBoundary(curPos);
+				}
+			}
+			return new SelectionState(textFlow, paraElAbsStart + curPos, curAbsStart);
+		}		
+		
+		/** 
+		 * @copy IEditManager#insertText()
+		 * @includeExample examples\EditManager_insertText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function insertText(text:String, origOperationState:SelectionState = null):void
+		{
+			// if there's another insert operation waiting to be executed, 
+			// just add to it, if possible
+			if (origOperationState == null && pendingInsert)
+				pendingInsert.text += text;
+			else 
+			{
+				var operationState:SelectionState = defaultOperationState(origOperationState);
+				if (!operationState)
+					return;
+				
+				// rather than execute the insert immediately, create
+				// it and wait for the next frame, in order to batch
+				// keystrokes.
+				pendingInsert = new InsertTextOperation(operationState, text);
+				
+				var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
+				if (captureLevel == 0 && origOperationState == null && controller && controller.container)
+				{
+					enterFrameListener = controller.container;
+					enterFrameListener.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 1.0, true);
+				}
+				else
+					flushPendingOperations();
+			}
+		}
+				
+
+		
+		/** 
+		 * @copy IEditManager#overwriteText()
+		 * 
+		 * @includeExample examples\EditManager_overwriteText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function overwriteText(text:String, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+			var selState:SelectionState = getSelectionState();
+			NavigationUtil.nextCharacter(selState,true);
+			doOperation(new InsertTextOperation(operationState, text, selState));
+		}
+
+		/** 
+		 * @copy IEditManager#insertInlineGraphic()
+		 * @includeExample examples\EditManager_insertInlineGraphic.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @see flash.text.engine.TextRotation
+		 */			
+		public function insertInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new InsertInlineGraphicOperation(operationState, source, width, height, options));
+		}	
+		
+		/** 
+		 * @copy IEditManager#modifyInlineGraphic()
+		 * @includeExample examples\EditManager_modifyInlineGraphic.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */			
+		public function modifyInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new ModifyInlineGraphicOperation(operationState, source, width, height, options));
+		}					
+		
+		/** 
+		 * @copy IEditManager#applyFormat()
+		 * 
+		 * @includeExample examples\EditManager_applyFormat.as -noswf
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function applyFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			// apply to the current selection else remember new format for next char typed
+			doOperation(new ApplyFormatOperation(operationState, leafFormat, paragraphFormat, containerFormat));
+		}
+		/** 
+		 * @copy IEditManager#clearFormat()
+		 * 
+		 * Known issue is that undefines of leafFormat values with a point selection are not applied at the next insertion.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public function clearFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+			
+			// apply to the current selection else remember new format for next char typed
+			doOperation(new ClearFormatOperation(operationState, leafFormat, paragraphFormat, containerFormat));
+		}
+		/** 
+		 * @copy IEditManager#applyLeafFormat()
+		 * 
+		 * @includeExample examples\EditManager_applyLeafFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function applyLeafFormat(characterFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			applyFormat(characterFormat, null, null, operationState);
+		}
+
+		/** 
+		 * @copy IEditManager#applyParagraphFormat()
+		 * 
+		 * @includeExample examples\EditManager_applyParagraphFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 		 */		
+		public function applyParagraphFormat(paragraphFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			applyFormat(null, paragraphFormat, null, operationState);
+		}
+
+		/** 
+		 * @copy IEditManager#applyContainerFormat()
+		 * 
+		 * @includeExample examples\EditManager_applyContainerFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		public function applyContainerFormat(containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			applyFormat(null, null, containerFormat, operationState);
+		}
+		
+		/** 
+		 * @copy IEditManager#applyFormatToElement()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function applyFormatToElement(targetElement:FlowElement, format:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new ApplyFormatToElementOperation(operationState, targetElement, format));
+		}
+
+		/** 
+		 * @copy IEditManager#clearFormatOnElement()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */	
+		public function clearFormatOnElement(targetElement:FlowElement, format:ITextLayoutFormat, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+			
+			doOperation(new ClearFormatOnElementOperation(operationState, targetElement, format));
+		}
+		
+		/** 
+		 * @copy IEditManager#cutTextScrap()
+		 * @includeExample examples\EditManager_cutTextScrap.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 *  @see flashx.textLayout.edit.TextScrap
+		 */
+		public function cutTextScrap(operationState:SelectionState = null):TextScrap
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return null;
+				
+			if (operationState.anchorPosition == operationState.activePosition)
+				return null;
+
+			var tScrap:TextScrap = TextFlowEdit.createTextScrap(operationState.textFlow, operationState.absoluteStart, operationState.absoluteEnd);			
+			var beforeOpLen:int = textFlow.textLength;						
+			doOperation(new CutOperation(operationState, tScrap));
+			if (operationState.textFlow.textLength != beforeOpLen)
+			{
+				return tScrap;
+			}									
+			return null;			
+		}
+		
+		/** 
+		 * @copy IEditManager#pasteTextScrap()
+		 * @includeExample examples\EditManager_pasteTextScrap.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 *  @see flashx.textLayout.edit.TextScrap
+		 */
+		public function pasteTextScrap(scrapToPaste:TextScrap, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new PasteOperation(operationState, scrapToPaste));	
+		}
+		
+		/** 
+		 * @copy IEditManager#applyTCY()
+		 * @includeExample examples\EditManager_applyTCY.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */			
+		public function applyTCY(tcyOn:Boolean, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+
+			doOperation(new ApplyTCYOperation(operationState, tcyOn));
+		}
+		
+		/** 
+		 * @copy IEditManager#applyLink()
+		 * @includeExample examples\EditManager_applyLink.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */			
+		public function applyLink(href:String, targetString:String = null, extendToLinkBoundary:Boolean=false, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+				
+			if (operationState.absoluteStart == operationState.absoluteEnd)
+				return;
+
+			doOperation(new ApplyLinkOperation(operationState, href, targetString, extendToLinkBoundary));
+		}
+		
+		/**
+		 * @copy IEditManager#changeElementID()
+		 * @includeExample examples\EditManager_changeElementID.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	*/
+		public function changeElementID(newID:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+				
+			if (operationState.absoluteStart == operationState.absoluteEnd)
+				return;
+
+			doOperation(new ApplyElementIDOperation(operationState, targetElement, newID, relativeStart, relativeEnd));
+		}
+		
+		
+		/**
+		 * @copy IEditManager#changeStyleName()
+		 * @includeExample examples\EditManager_changeStyleName.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+	 	*/
+		public function changeStyleName(newName:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void
+		{
+			operationState = defaultOperationState(operationState);
+			if (!operationState)
+				return;
+				
+			doOperation(new ApplyElementStyleNameOperation(operationState, targetElement, newName, relativeStart, relativeEnd));
+		}
+		
+		/* CompositeOperations
+			Normally when you call doOperation, it gets executed immediately. By calling beginCompositeOperation, you can instead accumulate the
+			operations into a CompositeOperation. The CompositeOperation is completed and returned when you call endCompositeOperation, and 
+			processing returns to normal state. The client code can then either call doOperation on the CompositeOperation that was returned, 
+			or just drop it if the operation should be aborted.
+			
+			The parentStack is a stack of pending CompositeOperations. 
+		*/
+		private var parentStack:Array;
+		
+		/** 
+		 * @copy IEditManager#beginCompositeOperation()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @includeExample examples\EditManager_beginCompositeOperation.as -noswf
+		 */
+		public function beginCompositeOperation():void
+		{
+			flushPendingOperations();
+			
+			if (!parentStack)
+				parentStack = [];
+			var operation:CompositeOperation = new CompositeOperation();
+			
+			if (!_imeSession)
+			{	
+				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,false,operation,captureLevel,null);
+				textFlow.dispatchEvent(opEvent);
+			}
+			
+			CONFIG::debug { assert(!operation.operations  || operation.operations.length == 0, "opening a composite operation that already has operations"); }
+			operation.setGenerations(textFlow.generation, 0);
+			++captureLevel;
+			var parent:Object = new Object();
+			parent.operation = operation;
+			parent.captureLevel = captureLevel;
+			parentStack.push(parent);
+		}
+		
+		/** 
+		 * @copy IEditManager#endCompositeOperation()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @includeExample examples\EditManager_beginCompositeOperation.as -noswf
+		 */
+		public function endCompositeOperation():void
+		{
+			CONFIG::debug { assert( parentStack.length > 0 || captureLevel <= 0, "EditManager.endOperation - no composite operation in progress"); }
+			
+			--captureLevel;
+			
+			var parent:Object = parentStack.pop();
+			var operation:FlowOperation = parent.operation;
+			if (!_imeSession)
+			{	
+				var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,false,operation,captureLevel,null);
+				textFlow.dispatchEvent(opEvent);
+			}
+			operation.setGenerations(operation.beginGeneration, textFlow.generation);
+			finalizeDo(operation);
+		}
+		
+		/** @private
+		 * Handler function called when the selection has been changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @param doDispatchEvent	true if a selection changed event will be sent
+		 * @param resetPointFormat	true if the attributes associated with the caret should be discarded
+		 */
+		tlf_internal override function selectionChanged(doDispatchEvent:Boolean = true, resetPointFormat:Boolean=true):void
+		{	
+			if (_imeSession)
+				_imeSession.selectionChanged();
+			
+			super.selectionChanged(doDispatchEvent, resetPointFormat);
+		}
+
+
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/ElementRange.as b/textLayout_edit/src/flashx/textLayout/edit/ElementRange.as
new file mode 100755
index 0000000..4f50fb7
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/ElementRange.as
@@ -0,0 +1,327 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+
+/**
+ * The ElementRange class represents the range of objects selected within a text flow.
+ * 
+ * <p>The beginning elements 
+ * (such as <code>firstLeaf</code>) are always less than or equal to the end elements (in this case, <code>lastLeaf</code>)
+ * for each pair of values in an element range.</p>
+ * 
+ * @see flashx.textLayout.elements.TextFlow
+ * 
+ * @playerversion Flash 10
+ * @playerversion AIR 1.5
+ * @langversion 3.0
+ */	
+public class ElementRange
+{
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	private var _absoluteStart:int;
+	private var _absoluteEnd:int;
+	private var _firstLeaf:FlowLeafElement;
+	private var _lastLeaf:FlowLeafElement;
+	private var _firstParagraph:ParagraphElement;
+	private var _lastParagraph:ParagraphElement;
+	private var _textFlow:TextFlow;	
+	
+	/** 
+	 * The absolute text position of the FlowLeafElement object that contains the start of the range.
+	 *  
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get absoluteStart():int
+	{
+		return _absoluteStart;
+	}
+	public function set absoluteStart(value:int):void
+	{
+		_absoluteStart = value;
+	}
+	
+	/** 
+	 * The absolute text position of the FlowLeafElement object that contains the end of the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+ 	 */
+	public function get absoluteEnd():int
+	{
+		return _absoluteEnd;
+	}
+	public function set absoluteEnd(value:int):void
+	{
+		_absoluteEnd = value;
+	}
+
+	/** 
+	 * The FlowLeafElement object that contains the start of the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get firstLeaf():FlowLeafElement
+	{
+		return _firstLeaf;
+	}
+	public function set firstLeaf(value:FlowLeafElement):void
+	{
+		_firstLeaf = value;
+	}
+
+	/** 
+	 * The FlowLeafElement object that contains the end of the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	*/
+	public function get lastLeaf():FlowLeafElement
+	{
+		return _lastLeaf;
+	}
+	public function set lastLeaf(value:FlowLeafElement):void
+	{
+		_lastLeaf = value;
+	}
+
+	/** 
+	 * The ParagraphElement object that contains the start of the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get firstParagraph():ParagraphElement
+	{
+		return _firstParagraph;
+	}
+	public function set firstParagraph(value:ParagraphElement):void
+	{
+		_firstParagraph = value;
+	}
+	
+	/** 
+	 * The ParagraphElement object that contains the end of the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	*/
+	public function get lastParagraph():ParagraphElement
+	{
+		return _lastParagraph;
+	}
+	public function set lastParagraph(value:ParagraphElement):void
+	{
+		_lastParagraph = value;
+	}
+	
+	/** 
+	 * The TextFlow object that contains the range. 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get textFlow():TextFlow
+	{
+		return _textFlow;
+	}	
+	public function set textFlow(value:TextFlow):void
+	{
+		_textFlow = value;
+	}	
+	
+	// This constructor function is here just to silence a compile warning in Eclipse. There
+	// appears to be no way to turn the warning off selectively.
+	/** @private */
+	CONFIG::debug public function ElementRange()
+	{
+		super();
+	}
+	
+ 	// NOTE: We've been back and forth on this - should a range selection show null attributes or beginning of range attributes?
+	// After looking at this for a while I want it to show beginning of range attributes.  Two main reasons
+	// 1. If the range contains different objects but homogoneous settings we should show the attributes.
+	// 2. If we show null attributes on a range selection there's no way to, for example, turn BOLD off.
+	// Try this at home - restore the old code. Select the entire text.  Turn Bold on.  Can't turn bold off.
+	// Please don't revert this without further discussion.
+	// Ideally we would have a way of figuring out which attributes are homogoneous over the selection range
+	// and which were not and showing, for example, a "half-checked" bold item.  We'd have to work this out for all the properties.
+	
+	// OLD CODE that shows null attribute settings on a range selection
+	// var charAttr:ICharacterFormat = selRange.begElem == selRange.endElem ? selRange.begElem.computedCharacterFormat : new CharacterFormat();
+	// var paraAttr:IParagraphFormat = selRange.begPara == selRange.endPara ? selRange.begPara.computedParagraphFormat : new ParagraphFormat();
+
+
+	/** 
+	 * The format attributes of the container displaying the range. 
+	 * 
+	 * <p>If the range spans more than one container, the format of the first container is returned.</p>
+	 *  
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get containerFormat():ITextLayoutFormat
+	{
+		// see NOTE above before changing!!
+		// This is just wrong - only shows the first container
+		var container:ContainerController;
+		var flowComposer:IFlowComposer = firstParagraph.getTextFlow().flowComposer;
+		if (flowComposer && flowComposer.numControllers > 0)
+			container = flowComposer.getControllerAt(0);
+		if (!container)
+			return ContainerFormattedElement(firstParagraph.getParentByType(ContainerFormattedElement)).computedFormat;
+ 		return container.computedFormat;		
+	}
+		
+	/** 
+	 * The format attributes of the paragraph containing the range. 
+	 * 
+	 * <p>If the range spans more than one paragraph, the format of the first paragraph is returned.</p>
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get paragraphFormat():ITextLayoutFormat
+	{
+		// see NOTE above before changing!!
+  		return firstParagraph.computedFormat;
+ 	}
+		
+	/** 
+	 * The format attributes of the characters in the range. 
+	 * 
+	 * <p>If the range spans more than one FlowElement object, which means that more than one
+	 * character format may exist within the range, the format of the first FlowElement object is returned.</p>
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public function get characterFormat():ITextLayoutFormat
+	{
+		// see NOTE above before changing!!
+ 		return firstLeaf.computedFormat;
+	}
+	
+	/** 
+	 * Creates an ElementRange object.
+	 * 
+	 * @param textFlow	the text flow
+	 * @param beginIndex absolute text position of the first character in the text range
+	 * @param endIndex one beyond the absolute text position of the last character in the text range
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	static public function createElementRange(textFlow:TextFlow, absoluteStart:int, absoluteEnd:int):ElementRange
+	{
+		var rslt:ElementRange = new ElementRange();
+		if (absoluteStart == absoluteEnd)
+		{
+			rslt.absoluteStart = rslt.absoluteEnd = absoluteStart;
+			rslt.firstLeaf = rslt.lastLeaf = textFlow.findLeaf(rslt.absoluteStart);
+			rslt.firstParagraph = rslt.lastParagraph = rslt.firstLeaf.getParagraph();
+	//		rslt.begContainer = rslt.endContainer = selState.textFlow.findAbsoluteContainer(rslt.begElemIdx);
+			adjustForLeanLeft(rslt);
+		}
+		else
+		{
+			// order the selection points
+			if (absoluteStart < absoluteEnd)
+			{
+				rslt.absoluteStart  = absoluteStart;
+				rslt.absoluteEnd = absoluteEnd;
+			}
+			else
+			{
+				rslt.absoluteStart  = absoluteEnd;
+				rslt.absoluteEnd = absoluteStart;
+			}
+			rslt.firstLeaf = textFlow.findLeaf(rslt.absoluteStart);
+			rslt.lastLeaf = textFlow.findLeaf(rslt.absoluteEnd);
+			// back up one element if the end of the selection is the start of an element
+			// otherwise a block selection of a span looks like it includes discreet selection ranges
+			if (((rslt.lastLeaf == null) && (rslt.absoluteEnd == textFlow.textLength)) || (rslt.absoluteEnd == rslt.lastLeaf.getAbsoluteStart()))
+				rslt.lastLeaf = textFlow.findLeaf(rslt.absoluteEnd-1);
+				
+			rslt.firstParagraph = rslt.firstLeaf.getParagraph();
+			rslt.lastParagraph = rslt.lastLeaf.getParagraph();
+			
+	//		rslt.begContainer = selState.textFlow.findAbsoluteContainer(rslt.begElemIdx);
+	//		rslt.endContainer = selState.textFlow.findAbsoluteContainer(rslt.endElemIdx);
+	//		if (rslt.endElemIdx == rslt.endContainer.relativeStart)
+	//			rslt.endContainer = rslt.endContainer.preventextContainer;
+				
+			// if the end of the range includes the next to last character in a paragraph 
+			// expand it to include the paragraph teriminate character
+			if (rslt.absoluteEnd == rslt.lastParagraph.getAbsoluteStart() + rslt.lastParagraph.textLength - 1)
+			{
+				rslt.absoluteEnd++
+				rslt.lastLeaf = rslt.lastParagraph.getLastLeaf();
+			}
+
+		}
+		rslt.textFlow = textFlow;
+			
+		return rslt;
+	}
+	
+	static private function adjustForLeanLeft(rslt:ElementRange):void
+	{		
+		// If we're at the start of a leaf element, look to the previous leaf element and see if it shares the same
+		// parent. If so, we're going to move the selection to the end of the previous element so it takes on
+		// the formatting of the character to the left. We don't want to do this if the previous element is in
+		// a different character, across link or tcy boundaries, etc.
+		if (rslt.firstLeaf.getAbsoluteStart() == rslt.absoluteStart)
+		{
+			var previousNode:FlowLeafElement = rslt.firstLeaf.getPreviousLeaf(rslt.firstParagraph);
+			if (previousNode && previousNode.getParagraph() == rslt.firstLeaf.getParagraph())
+			{
+				if((!(previousNode.parent is SubParagraphGroupElement) || (previousNode.parent as SubParagraphGroupElement).acceptTextAfter())
+					&& (!(rslt.firstLeaf.parent is SubParagraphGroupElement) || previousNode.parent === rslt.firstLeaf.parent))
+					rslt.firstLeaf = previousNode;
+			}
+				
+		}
+	}
+}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/edit/IEditManager.as b/textLayout_edit/src/flashx/textLayout/edit/IEditManager.as
new file mode 100755
index 0000000..cc5ca53
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/IEditManager.as
@@ -0,0 +1,644 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.geom.Rectangle;
+	
+	import flashx.undo.UndoManager;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.operations.CompositeOperation;
+	import flashx.textLayout.operations.FlowOperation;
+	
+	import flashx.undo.IOperation;
+	
+	/** 
+	 * IEditManager defines the interface for handling edit operations of a text flow.
+	 * 
+	 * <p>To enable text flow editing, assign an IEditManager instance to the <code>interactionManager</code> 
+	 * property of the TextFlow object. The edit manager handles changes to the text (such as insertions, 
+	 * deletions, and format changes). Changes are reversible if the edit manager has an undo manager. The edit
+	 * manager triggers the recomposition and display of the text flow, as necessary.</p>
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+ 	 * 
+ 	 * @see EditManager
+ 	 * @see flashx.textLayout.elements.TextFlow
+ 	 * @see flashx.undo.UndoManager
+ 	 * 
+	 */
+	public interface IEditManager extends ISelectionManager
+	{				
+
+		/** 
+		 * The UndoManager object assigned to this EditManager instance, if there is one.
+		 * 
+		 * <p>An undo manager handles undo and redo operations.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function get undoManager():flashx.undo.IUndoManager
+
+		/** 
+		 * Changes the formats of the specified (or current) selection.
+		 * 
+		 * <p>Executes an undoable operation that applies the new formats.
+		 * Only style attributes set for the TextLayoutFormat objects are applied.
+		 * Undefined attributes in the format objects are not changed.
+		 * </p>
+ 	 	 * 
+		 * @param leafFormat	the format to apply to leaf elements such as spans and inline graphics
+		 * @param paragraphFormat	format to apply to paragraph elements
+		 * @param containerFormat	format to apply to the containers
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 *
+ 	 	 * @includeExample examples\EditManager_applyFormat.as -noswf
+ 	 	 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		function applyFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+
+		
+		/** 
+		 * Undefines formats of the specified (or current) selection.
+		 * 
+		 * <p>Executes an undoable operation that undefines the specified formats.
+		 * Only style attributes set for the TextLayoutFormat objects are applied.
+		 * Undefined attributes in the format objects are not changed.
+		 * </p>
+		 * 
+		 * @param leafFormat	 The format whose set values indicate properties to undefine to LeafFlowElement objects in the selected range.
+		 * @param paragraphFormat The format whose set values indicate properties to undefine to ParagraphElement objects in the selected range.
+		 * @param containerFormat The format whose set values indicate properties to undefine to ContainerController objects in the selected range.
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		
+		function clearFormat(leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat, operationState:SelectionState = null):void
+
+		/** 
+		 * Changes the format applied to the leaf elements in the 
+		 * specified (or current) selection.
+		 * 
+		 * <p>Executes an undoable operation that applies the new format to leaf elements such as
+		 * SpanElement and InlineGraphicElement objects.
+		 * Only style attributes set for the TextLayoutFormat objects are applied.
+		 * Undefined attributes in the format object are changed.</p>
+		 * 
+		 * @param format	the format to apply.
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyLeafFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		function applyLeafFormat(format:ITextLayoutFormat, operationState:SelectionState = null):void;
+
+		/** 
+		 * Transforms text into a TCY run, or a TCY run into non-TCY text. 
+		 * 
+		 * <p>TCY, or tate-chu-yoko, causes text to draw horizontally within a vertical line, and is 
+		 * used to make small blocks of non-Japanese text or numbers, such as dates, more readable in vertical text.</p>
+		 * 
+		 * @param tcyOn	specify <code>true</code> to apply TCY to a text range, <code>false</code> to remove TCY. 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyTCY.as -noswf
+		 * @see flashx.textLayout.elements.TCYElement
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 		 */			
+		function applyTCY(tcyOn:Boolean, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Transforms a selection into a link, or a link into normal text.
+		 * 
+		 * <p>Executes an undoable operation that creates or removes the link.</p>
+		 * 
+		 *  <p>If a <code>target</code> parameter is specified, it must be one of the following values:</p>
+		 * <ul>
+		 *	<li>"_self"</li>
+		 *  <li>"_blank"</li>
+		 *  <li>"_parent"</li>
+		 *  <li>"_top"</li>
+         * </ul>
+		 * <p>In browser-hosted runtimes, a target of "_self" replaces the current html page.  
+		 * So, if the SWF content containing the link is in a page within
+		 * a frame or frameset, the linked content loads within that frame.  If the page 
+		 * is at the top level, the linked content opens to replace the original page.  
+		 * A target of "_blank" opens a new browser window with no name.  
+		 * A target of "_parent" replaces the parent of the html page containing the SWF content.  
+		 * A target of "_top" replaces the top-level page in the current browser window.</p>
+		 * 
+		 * <p>In other runtimes, such as Adobe AIR, the link opens in the user's default browser and the
+		 * <code>target</code> parameter is ignored.</p>
+		 * 
+		 * <p>The <code>extendToLinkBoundary</code> parameter determines how the edit manager 
+		 * treats a selection that intersects with one or more existing links. If the parameter is 
+		 * <code>true</code>, then the operation is applied as a unit to the selection and the
+		 * whole text of the existing links. Thus, a single link is created that spans from
+		 * the beginning of the first link intersected to the end of the last link intersected.
+		 * In contrast, if <code>extendToLinkBoundary</code> were <code>false</code> in this situation, 
+		 * the existing partially selected links would be split into two links.</p>
+		 *
+		 * @param href The uri referenced by the link.
+		 * @param target The target browser window of the link.
+		 * @param extendToLinkBoundary Specifies whether to consolidate selection with any overlapping existing links, and then apply the change.
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyLink.as -noswf
+		 * @see flashx.textLayout.elements.LinkElement
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */			
+		function applyLink(href:String, target:String=null, extendToLinkBoundary:Boolean=false, operationState:SelectionState = null):void;
+		
+		/**
+		* Changes the ID of an element.
+		* 
+		 * <p>If the <code>relativeStart</code> or <code>relativeEnd</code> parameters are set (to
+		 * anything other than the default values), then the element is split. The parts of the element
+		 * outside this range retain the original ID. Setting both the <code>relativeStart</code> and 
+		 * <code>relativeEnd</code> parameters creates elements with duplicate IDs.</p>
+		 * 
+		* @param newID the new ID value
+		* @param targetElement the element to modify
+		* @param relativeStart an offset from the beginning of the element at which to split the element when assigning the new ID
+		* @param relativeEnd an offset from the end of the element at which to split the element when assigning the new ID
+		* @param operationState	specifies the selection to restore when undoing this operation; 
+		* if <code>null</code>, the operation saves the current selection.
+		* 
+		 * @includeExample examples\EditManager_changeElementID.as -noswf
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0 
+	 	*/
+		function changeElementID(newID:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void;
+		
+		/**
+		* Changes the styleName of an element or part of an element.
+		 * 
+		 * <p>If the <code>relativeStart</code> or <code>relativeEnd</code> parameters are set (to
+		 * anything other than the default values), then the element is split. The parts of the element
+		 * outside this range retain the original style.</p>
+		 * 
+		* @param newName the name of the new style.
+		* @param targetElement specifies the element to change.
+		* @param relativeStart an offset from the beginning of the element at which to split the element when assigning the new style
+		* @param relativeEnd an offset from the end of the element at which to split the element when assigning the new style
+		* @param operationState	specifies the selection to restore when undoing this operation; 
+		* if <code>null</code>, the operation saves the current selection.
+		* 
+		 * @includeExample examples\EditManager_changeStyleName.as -noswf
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0 
+	 	*/
+		function changeStyleName(newName:String, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1, operationState:SelectionState = null):void;
+
+		/** 
+		 * Deletes a range of text, or, if a point selection is given, deletes the next character.
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_deleteNextCharacter.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function deleteNextCharacter(operationState:SelectionState = null):void;
+		
+		/** 
+		 * Deletes a range of text, or, if a point selection is given, deletes the previous character.
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_deletePreviousCharacter.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function deletePreviousCharacter(operationState:SelectionState = null):void;
+		
+		/** 
+		 * Deletes the next word.
+		 * 
+		 * <p>If a range is selected, the first word of the range is deleted.</p>
+		 * 
+		 * @param operationState specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_deleteNextWord.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		function deleteNextWord(operationState:SelectionState = null):void;
+		
+		/** 
+		 * Deletes the previous word.
+		 * 
+		 * <p>If a range is selected, the first word of the range is deleted.</p>
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_deletePreviousWord.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		function deletePreviousWord(operationState:SelectionState = null):void;		
+		
+		/** 
+		 * Deletes a range of text.
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_deleteText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function deleteText(operationState:SelectionState = null):void
+
+		/** 
+		 * Inserts an image.
+		 * 
+		 * <p>The source of the image can be a string containing a URI, URLRequest object, a Class object representing an embedded asset,
+		 * or a DisplayObject instance.</p>
+		 *  
+		 * <p>The width and height values can be the number of pixels, a percent, or the string, 'auto', 
+		 * in which case the actual dimension of the graphic is used.</p>
+		 * 
+		 * <p>Set the <code>float</code> to one of the constants defined in the Float class to specify whether
+		 * the image should be displayed to the left or right of any text or inline with the text.</p>
+		 * 
+		 *	@param	source	can be either a String interpreted as a uri, a Class interpreted as the class of an Embed DisplayObject, 
+		 * 					a DisplayObject instance or a URLRequest. 
+		 *	@param	width	width of the image to insert (number, percent, or 'auto')
+		 *	@param	height	height of the image to insert (number, percent, or 'auto')
+		 *	@param	options	none supported.
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_insertInlineGraphic.as -noswf
+		 * 
+		 * @see flashx.textLayout.elements.InlineGraphicElement
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 		 */			
+		function insertInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Modifies an existing inline graphic.
+		 * 
+		 * <p>Set unchanging properties to the values in the original graphic. (Modifying an existing graphic object
+		 * is typically more efficient than deleting and recreating one.)</p>
+		 * 
+		 *	@param	source	can be either a String interpreted as a uri, a Class interpreted as the class of an Embed DisplayObject, 
+		 * 					a DisplayObject instance or a URLRequest. 
+		 *	@param	width	new width for the image (number or percent)
+		 *	@param	height	new height for the image (number or percent)
+		 *	@param	options	none supported
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_modifyInlineGraphic.as -noswf
+		 * 
+		 *  @see flashx.textLayout.elements.InlineGraphicElement
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */			
+		function modifyInlineGraphic(source:Object, width:Object, height:Object, options:Object = null, operationState:SelectionState = null):void;
+
+		/** 
+		 * Inserts text.
+		 * 
+		 * <p>Inserts the text at a position or range in the text. If the location supplied in the 
+		 * <code>operationState</code> parameter is a range (or the parameter is <code>null</code> and the
+		 * current selection is a range), then the text currently in the range 
+		 * is replaced by the inserted text.</p>
+		 * 
+		 * @param	text		the string to insert
+		 * @param operationState	specifies the text in the flow to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_insertText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		function insertText(text:String, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Overwrites the selected text.
+		 * 
+		 * <p>If the selection is a point selection, the first character is overwritten by the new text.</p>
+		 * 
+		 * @param text the string to insert
+		 * @param operationState specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_overwriteText.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		function overwriteText(text:String, operationState:SelectionState = null):void;
+
+		/** 
+		 * Applies paragraph styles to any paragraphs in the selection.
+		 * 
+		 * <p>Any style properties in the format object that are <code>null</code> are left unchanged.</p> 
+		 * 
+ 	 	 * @param format the format to apply to the selected paragraphs.
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyParagraphFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 		 */		
+		function applyParagraphFormat(format:ITextLayoutFormat, operationState:SelectionState = null):void;
+
+		/** 
+		 * Applies container styles to any containers in the selection.
+		 * 
+		 * <p>Any style properties in the format object that are <code>null</code> are left unchanged.</p> 
+		 * 
+		 * @param format	the format to apply to the containers in the range
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyContainerFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */		
+		function applyContainerFormat(format:ITextLayoutFormat, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Applies styles to the specified element.
+		 * 
+		 * <p>Any style properties in the format object that are <code>null</code> are left unchanged.
+		 * Only styles that are relevant to the specified element are applied.</p> 
+		 * 
+		 * @param 	targetElement the element to which the styles are applied.
+		 * @param	format	the format containing the styles to apply
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_applyFormatToElement.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		function applyFormatToElement(targetElement:FlowElement, format:ITextLayoutFormat, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Undefines styles to the specified element.
+		 * 
+		 * <p>Any style properties in the format object that are <code>undefined</code> are left unchanged.
+		 * Any styles that are defined in the specififed format are undefined on the specified element.</p> 
+		 * 
+		 * @param 	targetElement the element to which the styles are applied.
+		 * @param	format	the format containing the styles to undefine
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */	
+		function clearFormatOnElement(targetElement:FlowElement, format:ITextLayoutFormat, operationState:SelectionState = null):void;
+		
+		/** 
+		 * Splits the paragraph at the current position.
+		 *   
+		 * <p>If a range of text is specified, the text 
+		 * in the range is deleted.</p>
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_splitParagraph.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function splitParagraph(operationState:SelectionState = null):void;
+		
+		/** 
+		 * Deletes the selected area and returns the deleted area in a TextScrap object. 
+		 * 
+		 * <p>The resulting TextScrap can be posted to the system clipboard or used in a 
+		 * subsequent <code>pasteTextOperation()</code> operation.</p>
+		 * 
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * @return the TextScrap that was cut
+		 * 
+		 * @includeExample examples\EditManager_cutTextScrap.as -noswf
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager.pasteTextScrap
+		 * @see flashx.textLayout.edit.TextClipboard.setContents
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		function cutTextScrap(operationState:SelectionState = null):TextScrap;
+		
+		/** 
+		 * Pastes the TextScrap into the selected area.
+		 * 
+		 * <p>If a range of text is specified, the text 
+		 * in the range is deleted.</p>
+		 * 
+		 * @param scrapToPaste	the TextScrap to paste
+		 * @param operationState	specifies the text to which this operation applies; 
+		 * if <code>null</code>, the operation applies to the current selection.
+		 * 
+		 * @includeExample examples\EditManager_pasteTextScrap.as -noswf
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager.cutTextScrap
+		 * @see flashx.textLayout.edit.TextClipboard.getContents
+		 * @see flashx.textLayout.edit.TextScrap
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */
+		 function pasteTextScrap(scrapToPaste:TextScrap, operationState:SelectionState = null):void;		
+
+		/** 
+		 * Begins a new group of operations. 
+		 * 
+		 * <p>All operations executed after the call to <code>beginCompositeOperation()</code>, and before the 
+		 * matching call to <code>endCompositeOperation()</code> are executed and grouped together as a single 
+		 * operation that can be undone as a unit.</p> 
+		 * 
+		 * <p>A <code>beginCompositeOperation</code>/<code>endCompositeOperation</code> block can be nested inside another 
+		 * <code>beginCompositeOperation</code>/<code>endCompositeOperation</code> block.</p>
+		 * 
+		 * @includeExample examples\EditManager_beginCompositeOperation.as -noswf
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager.endCompositeOperation
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function beginCompositeOperation():void;
+		
+		/** 
+		 * Ends a group of operations. 
+		 * 
+		 * <p>All operations executed since the last call to <code>beginCompositeOperation()</code> are 
+		 * grouped as a CompositeOperation that is then completed. This CompositeOperation object is added 
+		 * to the undo stack or, if this composite operation is nested inside another composite operation, 
+		 * added to the parent operation.</p>
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager.beginCompositeOperation
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function endCompositeOperation():void;
+
+		/** 
+		 * Executes a FlowOperation.  
+		  * 
+		  * <p>The <code>doOperation()</code> method is called by IEditManager functions that 
+		  * update the text flow. You do not typically need to call this function directly unless 
+		  * you create your own custom operations.</p>
+		  * 
+		  * <p>This function proceeds in the following steps:</p>
+		  * <ol>
+		  * <li>Flush any pending operations before performing this operation.</li>
+		  * <li>Send a cancelable flowOperationBegin event.  If canceled this method returns immediately.</li>
+		  * <li>Execute the operation.  The operation returns <code>true</code> or <code>false</code>.  
+		  * <code>False</code> indicates that no changes were made.</li>
+		  * <li>Push the operation onto the undo stack.</li>
+		  * <li>Clear the redo stack.</li>
+		  * <li>Update the display.</li>
+		  * <li>Send a cancelable flowOperationEnd event.</li>
+		  * </ol>
+		  * <p>Exception handling:  If the operation throws an exception, it is caught and the error is 
+		  * attached to the flowOperationEnd event.  If the event is not canceled the error is rethrown.</p>
+		  * 
+		  * @param operation a FlowOperation object
+		  * 
+		  * @includeExample examples\EditManager_doOperation.as -noswf
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+ 	 	  * @langversion 3.0
+		  */
+		function doOperation(operation:FlowOperation):void;
+
+		/** 
+		 * Reverses the previous operation. 
+		 * 
+		 * <p><b>Note:</b> If the IUndoManager associated with this IEditManager is also associated with 
+		 * another IEditManager, then it is possible that the undo operation associated with the other 
+		 * IEditManager is the one undone.  This can happen if the FlowOperation of another IEditManager 
+		 * is on top of the undo stack.</p>  
+		 * 
+		 * <p>This function does nothing if undo is not turned on.</p>
+		 * 
+		 * @includeExample examples\EditManager_undo.as -noswf
+		 * 
+		 * @see flashx.undo.IUndoManager#undo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function undo():void;
+
+		/** 
+		 * Reperforms the previous undone operation.
+		 * 
+		 * <p><b>Note:</b> If the IUndoManager associated with this IEditManager is also associated with 
+		 * another IEditManager, then it is possible that the redo operation associated with the other 
+		 * IEditManager is the one redone. This can happen if the FlowOperation of another IEditManager 
+		 * is on top of the redo stack.</p>  
+		 * 
+		 * <p>This function does nothing if undo is not turned on.</p>
+		 * 
+		 * @includeExample examples\EditManager_redo.as -noswf
+		 * 
+		 * @see flashx.undo.IUndoManager#redo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function redo():void;
+		
+		/** @private */
+		function performUndo(operation:IOperation):void;
+
+		/** @private */
+		function performRedo(operation:IOperation):void;
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/IMEClient.as b/textLayout_edit/src/flashx/textLayout/edit/IMEClient.as
new file mode 100755
index 0000000..b165d1d
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/IMEClient.as
@@ -0,0 +1,376 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit {
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.system.IME;
+	import flash.text.engine.TextLine;
+	import flash.text.ime.CompositionAttributeRange;
+	import flash.text.ime.IIMEClient;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.IMEStatus;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.operations.ApplyElementUserStyleOperation;
+	import flashx.textLayout.operations.InsertTextOperation;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.GeometryUtil;
+	import flashx.undo.IOperation;
+	import flashx.undo.UndoManager;
+	
+	use namespace tlf_internal;
+
+	internal class IMEClient implements IIMEClient
+	{
+		private var _editManager:EditManager;
+		private var _undoManager:UndoManager;
+
+		/** Maintain position of text we've inserted while in the middle of processing IME. */
+		private var _imeAnchorPosition:int;		// start of IME text
+		private var _imeLength:int;				// length of IME text
+		private var _controller:ContainerController;		// controller that had focus at the start of the IME session -- we want this one to keep focus
+		private var _closing:Boolean;
+		CONFIG::debug { 
+			private var _imeOperation:IOperation; 	// IME in-progress edits - used for debugging to confirm that operation we're undoing is the one we did via IME
+		}
+		
+		public function IMEClient(editManager:EditManager)
+		{
+			_editManager = editManager;
+			_imeAnchorPosition = _editManager.absoluteStart;
+			if (_editManager.textFlow)
+			{
+				var flowComposer:IFlowComposer = _editManager.textFlow.flowComposer;
+				if (flowComposer) 
+				{
+					var controllerIndex:int = flowComposer.findControllerIndexAtPosition(_imeAnchorPosition);
+					_controller = flowComposer.getControllerAt(controllerIndex);
+					if (_controller)
+						_controller.setFocus();
+				}
+			}
+			_closing = false;
+			if (_editManager.undoManager == null)
+			{
+				_undoManager = new UndoManager();
+				_editManager.setUndoManager(_undoManager);
+			}
+		}
+		
+		/** @private
+		 * Handler function called when the selection has been changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function selectionChanged():void
+		{	
+		//	trace("IMEClient.selectionChanged", _editManager.anchorPosition, _editManager.activePosition);
+			
+			// If we change the selection to something outside the session, abort the 
+			// session. If we just moved the selection within the session, we tell the IME about the changes.
+			if (_editManager.absoluteStart > _imeAnchorPosition + _imeLength || _editManager.absoluteEnd < _imeAnchorPosition)
+			{
+				//trace("selection changed to out of IME session");
+				compositionAbandoned();
+			}
+			else 
+			{
+				// This code doesn't with current version of Argo, but should work in future
+				//trace("selection changed within IME session");
+			//	var imeCompositionSelectionChanged:Function = IME["compositionSelectionChanged"];
+			//	if (IME["compositionSelectionChanged"] !== undefined)
+			 //		imeCompositionSelectionChanged(_editManager.absoluteStart - _imeAnchorPosition, _editManager.absoluteEnd - (_imeAnchorPosition + _imeLength));
+			}
+		}
+
+		private function doIMEClauseOperation(selState:SelectionState, clause:int):void
+		{
+ 		    var leaf:FlowLeafElement = _editManager.textFlow.findLeaf(selState.absoluteStart);;
+		    var leafAbsoluteStart:int = leaf.getAbsoluteStart();
+			_editManager.doOperation(new ApplyElementUserStyleOperation(selState, leaf, IMEStatus.IME_CLAUSE, clause.toString(), selState.absoluteStart - leafAbsoluteStart, selState.absoluteEnd - leafAbsoluteStart));
+		}
+		
+		private function doIMEStatusOperation(selState:SelectionState, attrRange:CompositionAttributeRange):void
+		{
+			var imeStatus:String;
+			
+			// Get the IME status from the converted & selected flags
+			if (attrRange == null)
+				imeStatus = IMEStatus.DEAD_KEY_INPUT_STATE;
+    		else if (!attrRange.converted)
+    		{
+    			if(!attrRange.selected)
+    				imeStatus = IMEStatus.NOT_SELECTED_RAW;
+    			else
+    				imeStatus = IMEStatus.SELECTED_RAW;
+    		}
+    		else
+    		{
+    			if (!attrRange.selected)
+    				imeStatus = IMEStatus.NOT_SELECTED_CONVERTED;
+    			else
+    				imeStatus = IMEStatus.SELECTED_CONVERTED;
+    		}
+
+
+			// refind since the previous operation changed the spans
+    		var leaf:FlowLeafElement = _editManager.textFlow.findLeaf(selState.absoluteStart);
+			CONFIG::debug { assert(	leaf != null, "found null FlowLeafELement at" + (selState.absoluteStart).toString()); }						    		
+    		var leafAbsoluteStart:int = leaf.getAbsoluteStart();
+
+			_editManager.doOperation(new ApplyElementUserStyleOperation(selState, leaf, IMEStatus.IME_STATUS, imeStatus, selState.absoluteStart - leafAbsoluteStart, selState.absoluteEnd - leafAbsoluteStart));
+		}
+		
+		// IME-related functions
+		public function updateComposition(text:String, attributes:Vector.<CompositionAttributeRange>, compositionStartIndex:int, compositionEndIndex:int):void
+	    {
+		//	CONFIG::debug { Debugging.traceOut("updateComposition ", compositionStartIndex, compositionEndIndex, text.length); }
+		//	CONFIG::debug { Debugging.traceOut("updateComposition selection ", _editManager.absoluteStart, _editManager.absoluteEnd); }
+			
+			// Undo the previous interim ime operation, if there is one. This deletes any text that came in a previous updateComposition call.
+			// Doing it via undo keeps the undo stack in sync.
+			if (_imeLength > 0 && _editManager.undoManager.peekUndo() != null)
+			{
+				CONFIG::debug { assert(_editManager.undoManager.peekUndo() == _imeOperation, "Unexpected operation in undo stack at end of IME update"); }
+				if (_editManager.undoManager)
+					_editManager.undoManager.undo();
+				_imeLength = 0; // prevent double deletion
+				CONFIG::debug {  _imeOperation = null; }
+			}
+
+			if (text.length > 0)
+			{
+				// Insert the supplied string, using the current editing format.
+				var pointFormat:ITextLayoutFormat = _editManager.getSelectionState().pointFormat;
+				var selState:SelectionState = new SelectionState(_editManager.textFlow, _imeAnchorPosition, _imeAnchorPosition + _imeLength, pointFormat);
+				
+				_editManager.beginIMEOperation();
+				
+				if (_editManager.absoluteStart != _editManager.absoluteEnd)
+					_editManager.deleteText();		// delete current selection
+				
+				var insertOp:InsertTextOperation = new InsertTextOperation(selState, text);
+				_imeLength = text.length;
+				_editManager.doOperation(insertOp);
+				
+				if (attributes && attributes.length > 0)
+				{
+					var attrLen:int = attributes.length;
+					for (var i:int = 0; i < attrLen; i++)
+					{
+						var attrRange:CompositionAttributeRange = attributes[i];
+						var clauseSelState:SelectionState = new SelectionState(_editManager.textFlow, _imeAnchorPosition + attrRange.relativeStart, _imeAnchorPosition + attrRange.relativeEnd);
+						
+						doIMEClauseOperation(clauseSelState, i);
+						doIMEStatusOperation(clauseSelState, attrRange);
+					}
+				}
+				else // composing accented characters
+				{	
+					clauseSelState = new SelectionState(_editManager.textFlow, _imeAnchorPosition, _imeAnchorPosition + _imeLength, pointFormat);
+					doIMEClauseOperation(clauseSelState, 0);
+					doIMEStatusOperation(clauseSelState, null);
+				}
+				
+				var newSelectionStart:int = _imeAnchorPosition + compositionStartIndex;
+				var newSelectionEnd:int = _imeAnchorPosition + compositionEndIndex;
+				if (_editManager.absoluteStart != newSelectionStart || _editManager.absoluteEnd != newSelectionEnd)
+				{
+					_editManager.selectRange(_imeAnchorPosition + compositionStartIndex, _imeAnchorPosition + compositionEndIndex);
+				}
+
+				CONFIG::debug {  _imeOperation = null; }
+				_editManager.endIMEOperation();	
+				CONFIG::debug {  _imeOperation = _editManager.undoManager.peekUndo(); }
+			}
+	    }
+	    
+	    public function confirmComposition(text:String = null, preserveSelection:Boolean = false):void
+		{
+		//	trace("confirmComposition", text, preserveSelection);
+			endIMESession();
+		}
+		
+		public function compositionAbandoned():void
+		{
+		//	trace("compositionAbandoned");
+
+			// In Argo we could just do this:
+			// IME.compositionAbandoned();
+			// but for support in Astro/Squirt where this API is undefined we do this:
+			var imeCompositionAbandoned:Function = IME["compositionAbandoned"];
+			if (IME["compositionAbandoned"] !== undefined)
+				imeCompositionAbandoned();
+		}
+		
+		private function endIMESession():void
+		{
+			if (!_editManager || _closing)
+				return;
+			
+			_closing = true;
+			
+			// Undo the IME operation. We're going to re-add the text, without all the special attributes, as part of handling
+			// the textInput event that comes next.
+			if (_imeLength > 0)
+			{
+				if (_editManager.undoManager.peekUndo() != null)
+				{
+					//trace("undoing imeOperation at end of IME session");
+					CONFIG::debug { assert(_editManager.undoManager.peekUndo() == _imeOperation, "Unexpected operation in undo stack at end of IME session"); }
+					if (_editManager.undoManager)
+						_editManager.undoManager.undo();
+					CONFIG::debug { assert(_editManager.undoManager.peekRedo() == _imeOperation, "Unexpected operation in redo stack at end of IME session"); }
+					_editManager.undoManager.popRedo();
+				}
+			}
+
+			if (_undoManager)
+				_editManager.setUndoManager(null);
+
+			// Clear IME state - tell EditManager to release IMEClient to finally close session
+			_editManager.endIMESession();
+			_editManager = null;
+		}
+		
+		public function getTextBounds(startIndex:int, endIndex:int):Rectangle
+		{
+			if(startIndex >= 0 && startIndex < _editManager.textFlow.textLength && endIndex >= 0 && endIndex < _editManager.textFlow.textLength)
+			{
+				if (startIndex != endIndex)
+				{
+					var boundsResult:Array = GeometryUtil.getHighlightBounds(new TextRange(_editManager.textFlow, startIndex, endIndex));
+				    //bail out if we don't have any results to show
+					if (boundsResult.length > 0)
+					{
+						var bounds:Rectangle = boundsResult[0].rect; 
+					    var textLine:TextLine = boundsResult[0].textLine; 
+					    var resultTopLeft:Point = textLine.localToGlobal(bounds.topLeft);
+					    var resultBottomRight:Point = textLine.localToGlobal(bounds.bottomRight);
+						if (textLine.parent)
+						{
+							var containerTopLeft:Point = textLine.parent.globalToLocal(resultTopLeft);
+							var containerBottomLeft:Point = textLine.parent.globalToLocal(resultBottomRight);
+							return new Rectangle(containerTopLeft.x, containerTopLeft.y, containerBottomLeft.x - containerTopLeft.x, containerBottomLeft.y - containerTopLeft.y);
+						}
+					}
+				}
+				else
+				{
+					var flowComposer:IFlowComposer = _editManager.textFlow.flowComposer;
+					var lineIndex:int = flowComposer.findLineIndexAtPosition(startIndex);
+	
+					// Stick to the end of the last line
+					if (lineIndex == flowComposer.numLines)
+						lineIndex--;
+					if (flowComposer.getLineAt(lineIndex).controller == _controller)
+					{
+						var line:TextFlowLine = flowComposer.getLineAt(lineIndex);
+						var previousLine:TextFlowLine = lineIndex != 0 ? flowComposer.getLineAt(lineIndex-1) : null;
+						var nextLine:TextFlowLine = lineIndex != flowComposer.numLines-1 ? flowComposer.getLineAt(lineIndex+1) : null;
+						return line.computePointSelectionRectangle(startIndex, _controller.container, previousLine, nextLine, true);
+					}
+				}
+			}
+			
+			return new Rectangle(0,0,0,0);
+		}
+		
+		public function get compositionStartIndex():int
+		{
+		//	trace("compositionStartIndex");
+			return _imeAnchorPosition;
+		}
+		
+		public function get compositionEndIndex():int
+		{
+		//	trace("compositionEndIndex");
+			return _imeAnchorPosition + _imeLength;
+		}
+		
+		public function get verticalTextLayout():Boolean
+		{
+		//	trace("verticalTextLayout");
+			return _editManager.textFlow.computedFormat.blockProgression == BlockProgression.RL;
+		}
+
+		public function get selectionActiveIndex():int
+		{
+			//trace("selectionActiveIndex");
+			return _editManager.activePosition;
+		}
+		
+		public function get selectionAnchorIndex():int
+		{
+			//trace("selectionAnchorIndex");
+			return _editManager.anchorPosition;
+		}
+		
+		public function selectRange(anchorIndex:int, activeIndex:int):void
+		{
+			_editManager.selectRange(anchorIndex, activeIndex);
+		}
+
+		public function setFocus():void
+		{
+			if (_controller && _controller.container && _controller.container.stage && _controller.container.stage.focus != _controller.container)
+				_controller.setFocus();
+		}
+		
+		/** 
+		 * Gets the specified range of text from a component implementing ITextSupport.
+		 * To retrieve all text in the component, do not specify values for <code>startIndex</code> and <code>endIndex</code>.
+		 * Components which wish to support inline IME or web searchability should call into this method.
+		 * Components overriding this method should ensure that the default values of <code>-1</code> 
+		 * for <code>startIndex</code> and <code>endIndex</code> are supported.
+		 * 
+		 * @playerversion Flash 10.0
+		 * @langversion 3.0
+		 */
+		public function getTextInRange(startIndex:int, endIndex:int):String
+		{
+			//trace("getTextInRange");
+			// Check for valid indices
+			var textFlow:TextFlow = _editManager.textFlow;
+			if (startIndex < -1 || endIndex < -1 || startIndex > (textFlow.textLength - 1) || endIndex > (textFlow.textLength - 1))
+				return null;
+			
+			// Make sure they're in the right order
+			if (endIndex < startIndex)
+			{
+				var tempIndex:int = endIndex;
+				endIndex = startIndex;
+				startIndex = tempIndex;
+			}
+			
+			if (startIndex == -1)
+				startIndex = 0;
+			
+			return textFlow.getText(startIndex, endIndex);
+		} 
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/edit/Mark.as b/textLayout_edit/src/flashx/textLayout/edit/Mark.as
new file mode 100755
index 0000000..8091a7c
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/Mark.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.edit
+{
+[ExcludeClass]
+
+	/** @private - not ready for prime time */
+	public class Mark
+	{
+		private var _position:int;
+
+		public function Mark(value:int = 0)
+		{
+			_position = value;
+		}
+		
+		public function get position():int
+			{ return _position; }
+		public function set position(value:int):void
+			{ _position = value; }
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/edit/ParaEdit.as b/textLayout_edit/src/flashx/textLayout/edit/ParaEdit.as
new file mode 100755
index 0000000..9831e90
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/ParaEdit.as
@@ -0,0 +1,653 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	[ExcludeClass]
+	/**
+	 * Encapsulates all methods necessary for dynamic editing of a text.  The methods are all static member functions of this class.
+	 * @private - because we can't make it tlf_internal. Used by the operations package 
+	 */
+ 	public class ParaEdit
+	{
+		/**
+		 * Inserts text into specified paragraph
+		 * @param p		ParagraphElement to insert into
+		 * @param paraSelBegIdx	index relative to beginning of the paragraph to insert text
+		 * @param leanBack  at an attribute change boundary are we on the left or the right
+		 * @param text	actual text to insert 
+		 * @param forceIntoLeafGiven	flag to suppress creation of new leaf element during insert (useful for type-to-replace)
+		 */
+		public static function insertText(para:ParagraphElement, elem:FlowLeafElement, paraSelBegIdx:int,insertText:String, forceIntoLeafGiven:Boolean = false):void
+		{
+			if (insertText.length == 0)
+				return;	// error? other sanity checks needed here?
+				
+			var createNewSpan:Boolean = false;
+			var insertParent:FlowGroupElement = elem.parent;
+			
+			var curSPGElement:SubParagraphGroupElement = elem.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
+			while (curSPGElement != null)
+			{
+				var subParInsertionPoint:int = paraSelBegIdx - curSPGElement.getElementRelativeStart(para);
+				if (((subParInsertionPoint == 0) && (!curSPGElement.acceptTextBefore())) ||
+					((!curSPGElement.acceptTextAfter() && (subParInsertionPoint == curSPGElement.textLength || 
+					(subParInsertionPoint == curSPGElement.textLength - 1 && (elem == para.getLastLeaf()))))))
+				{
+					createNewSpan = !forceIntoLeafGiven;
+					insertParent = insertParent.parent;
+					curSPGElement = curSPGElement.getParentByType(SubParagraphGroupElement) as SubParagraphGroupElement;
+				} else {
+					break;
+				}
+			}
+				
+			// adjust the flow so that we are in a span for the insertion
+			if ((!(elem is SpanElement)) || (createNewSpan == true))
+			{
+				var newSpan:SpanElement;	// scratch
+				var insertIdx:int;	// scratch
+				
+				// if were not in a span then we must be at the beginning or end of some other FlowLeafElement.  
+				// go to prev or next and use if it is a span.  add a span if needed.
+				var paraRelativeStart:int = elem.getElementRelativeStart(para);
+				CONFIG::debug{ assert(paraRelativeStart == paraSelBegIdx || paraRelativeStart+elem.textLength == paraSelBegIdx || paraRelativeStart+elem.textLength - 1 == paraSelBegIdx,"selection inside non-SpanElement Leaf"); }
+				if (paraRelativeStart == paraSelBegIdx)
+				{
+					elem = elem.getPreviousLeaf(para);
+					if (!(elem is SpanElement))
+					{
+						newSpan = new SpanElement();
+						if (elem)
+						{
+							newSpan.format = elem.format;
+							insertIdx = insertParent.getChildIndex(elem)+1;
+						}
+						else
+						{
+							newSpan.format = para.getFirstLeaf().format;
+							insertIdx = 0;
+						}
+						insertParent.replaceChildren(insertIdx,insertIdx,newSpan);
+						elem = newSpan;
+					}
+				}
+				else
+				{
+					newSpan = new SpanElement();
+					newSpan.format = elem.format;
+					if(elem.parent == insertParent)
+						insertIdx = insertParent.getChildIndex(elem)+1;
+					else
+						insertIdx = insertParent.getChildIndex(elem.parent)+1;
+						
+					insertParent.replaceChildren(insertIdx,insertIdx,newSpan);
+					elem = newSpan;
+				}
+			}
+			
+			var curSpan:SpanElement = elem as SpanElement;
+			var runInsertionPoint:int;
+			//if we added a new span, then 
+			runInsertionPoint = paraSelBegIdx - curSpan.getElementRelativeStart(para);
+			
+				
+			curSpan.replaceText(runInsertionPoint, runInsertionPoint, insertText);
+		}
+		
+		private static function deleteTextInternal(para:ParagraphElement, paraSelBegIdx:int, totalToDelete:int):void
+		{
+			var composeNode:FlowElement;
+			var curSpan:SpanElement;
+			
+			var curNumToDelete:int;
+			var curSpanDeletePos:int = 0;
+			
+			while (totalToDelete > 0)
+			{
+				composeNode = para.findLeaf(paraSelBegIdx);
+				CONFIG::debug { assert(composeNode is SpanElement,"deleteTextInternal: leaf element is not a span"); }
+								
+				curSpan = composeNode as SpanElement;
+				var curSpanRelativeStart:int = curSpan.getElementRelativeStart(para);
+				curSpanDeletePos = paraSelBegIdx - curSpanRelativeStart;
+				if (paraSelBegIdx > (curSpanRelativeStart + curSpan.textLength))
+				{
+					curNumToDelete = curSpan.textLength;
+				}
+				else
+				{
+					curNumToDelete = (curSpanRelativeStart + curSpan.textLength) - paraSelBegIdx;
+				}
+				
+				if (totalToDelete < curNumToDelete)
+				{
+					curNumToDelete = totalToDelete;
+				}
+				
+				curSpan.replaceText(curSpanDeletePos, curSpanDeletePos + curNumToDelete, "");
+				if (curSpan.textLength == 0)
+				{
+					var delIdx:int = curSpan.parent.getChildIndex(curSpan);
+					curSpan.parent.replaceChildren(delIdx,delIdx+1,null);						
+				}
+				totalToDelete -= curNumToDelete;
+			}			
+		}
+		
+		public static function deleteText(para:ParagraphElement, paraSelBegIdx:int, totalToDelete:int):void
+		{
+			var lastParPos:int = para.textLength - 1;
+			if ((paraSelBegIdx < 0) || (paraSelBegIdx > lastParPos))
+			{
+				//not much we can do. There's nothing to delete in this paragraph
+				return;
+			}
+			
+			if (totalToDelete <= 0)
+			{
+				//can't delete a negative number of characters... just return
+				return;
+			}
+			
+			var endPos:int = paraSelBegIdx + totalToDelete - 1;
+			if (endPos > lastParPos)
+			{
+				endPos = lastParPos;
+				totalToDelete = endPos - paraSelBegIdx + 1
+			}
+			
+			deleteTextInternal(para,paraSelBegIdx,totalToDelete);
+		}
+		
+		/**
+		 * Creates image and inserts it into specified FlowGroupElement
+		 * @param flowBlock	FlowGroupElement to insert image into
+		 * @param flowSelBegIdx	index relative to beginning of the FlowGroupElement to insert image
+		 * @param urlString	the url of image to insert
+		 * @param width	the width of the image
+		 * @param height the height of the image
+		 * @param options none supported
+		 */
+		public static function createImage(flowBlock:FlowGroupElement, flowSelBegIdx:int,source:Object, width:Object, height:Object, options:Object, pointFormat:ITextLayoutFormat):InlineGraphicElement
+		{
+			//first, split the element that we are on
+			var curComposeNode:FlowElement = flowBlock.findLeaf(flowSelBegIdx);
+			var posInCurComposeNode:int = 0;
+			if (curComposeNode != null)
+			{
+				posInCurComposeNode = flowSelBegIdx - curComposeNode.getElementRelativeStart(flowBlock); // curComposeNode.parentRelativeStart;
+			}			
+			
+			if ((curComposeNode != null) && (posInCurComposeNode > 0) && (posInCurComposeNode < curComposeNode.textLength))
+			{
+				//it is a LeafElement, and not position 0. It has to be a Span 
+				(curComposeNode as SpanElement).splitAtPosition(posInCurComposeNode);
+			}
+			
+			//the FlowElement or FlowGroupElement is now split.  Insert the image now.
+			var imgElem:InlineGraphicElement = new InlineGraphicElement();
+			imgElem.height = height;
+			imgElem.width = width;
+			imgElem.float = options ? options.toString() : Float.NONE;
+			
+			var src:Object = source;
+			var embedStr:String = "@Embed";
+			if (src is String && src.length > embedStr.length && src.substr(0, embedStr.length) == embedStr) {
+				// we should be dealing with an embedded asset. They are of the form "url=@Embed(source='path-to-asset')"
+				var searchStr:String = "source=";
+				var index:int = src.indexOf(searchStr, embedStr.length);
+				if (index > 0) {
+					index += searchStr.length;
+					index = src.indexOf("'", index);
+					src = src.substring(index+1, src.indexOf("'", index+1));
+				}
+			}
+			imgElem.source = src;
+			
+			while (curComposeNode && curComposeNode.parent != flowBlock)
+			{
+				curComposeNode = curComposeNode.parent;
+			}
+
+			var elementIdx:int = curComposeNode != null ? flowBlock.getChildIndex(curComposeNode) : flowBlock.numChildren;
+			if (curComposeNode && posInCurComposeNode > 0)
+				elementIdx++;
+			flowBlock.replaceChildren(elementIdx,elementIdx,imgElem);
+			
+			//clone characterFormat from the left OR iff the the first element the right
+			var p:ParagraphElement = imgElem.getParagraph();
+			var attrElem:FlowLeafElement = imgElem.getPreviousLeaf(p);
+			if (!attrElem)
+				attrElem = imgElem.getNextLeaf(p);
+			CONFIG::debug { assert(attrElem != null, "no element to get attributes from"); }
+			
+			if (attrElem.format || pointFormat)
+			{
+				var imageElemFormat:TextLayoutFormat = new TextLayoutFormat(attrElem.format);
+				if (pointFormat)
+					imageElemFormat.apply(pointFormat);
+				imgElem.format = imageElemFormat;
+			}
+			return imgElem;			
+		}		
+		
+		/** Merge changed attributes into this
+		 */
+		static private function splitForChange(span:SpanElement,begIdx:int,rangeLength:int):SpanElement
+		{
+			var startOffset:int = span.getAbsoluteStart();
+			if (begIdx == startOffset && rangeLength == span.textLength)
+				return span;
+				
+			// element must be split into spans
+			var elemToUpdate:SpanElement;
+			var origLength:int = span.textLength;
+			
+			var begRelativeIdx:int = begIdx - startOffset;
+			if (begRelativeIdx > 0)
+			{
+				// We create an initial span to hold the text before the new span, then
+				// a following span for the specified range.
+				elemToUpdate = span.splitAtPosition(begRelativeIdx) as SpanElement;
+				if (begRelativeIdx + rangeLength < origLength)
+					elemToUpdate.splitAtPosition(rangeLength);
+			}
+			else
+			{
+				// The specified range falls at the start of the element, so this span is the 
+				// one that's getting the new format.
+				span.splitAtPosition(rangeLength);
+				elemToUpdate = span;
+			}
+
+			return elemToUpdate;
+		}
+		
+		private static function undefineDefinedFormats(target:TextLayoutFormatValueHolder,undefineFormat:ITextLayoutFormat):void
+		{
+			if (undefineFormat)
+			{
+				// this is fairly rare so this operation is not optimizied
+				for (var prop:String in TextLayoutFormat.description)
+				{
+					if (undefineFormat[prop] !== undefined)
+						target[prop] = undefined;
+				} 
+			}
+		}
+
+		/**
+		 * Apply formatting changes to a range of text in the FlowElement
+		 *
+		 * @param begIdx	text index of first text in span
+		 * @param rangeLength	number of characters to modify
+		 * @param applyFormat		Character Format to apply to content
+		 * @param undefineFormat	Character Format to undefine to content
+		 * @return begIdx + number of actual actual characters modified.
+		 */
+		static private function applyCharacterFormat(leaf:FlowLeafElement, begIdx:int, rangeLength:int, applyFormat:ITextLayoutFormat, undefineFormat:ITextLayoutFormat):int
+		{
+			var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(leaf.format);
+			if (applyFormat)
+				newFormat.apply(applyFormat);
+			undefineDefinedFormats(newFormat,undefineFormat);
+			return setCharacterFormat(leaf, newFormat, begIdx, rangeLength);
+		}
+		
+		/**
+		 * Set formatting to a range of text in the FlowElement
+		 *
+		 * @param format	Character Format to apply to content
+		 * @param begIdx	text index of first text in span
+		 * @param rangeLength	number of characters to modify
+		 * @return starting position of following span
+		 */
+		static private function setCharacterFormat(leaf:FlowLeafElement, format:Object, begIdx:int, rangeLength:int):int
+		{
+			var startOffset:int = leaf.getAbsoluteStart();
+			if (!(format is ITextLayoutFormat) || !TextLayoutFormat.isEqual(ITextLayoutFormat(format),leaf.format))
+			{				
+				var para:ParagraphElement = leaf.getParagraph();
+				var paraStartOffset:int = para.getAbsoluteStart();
+				
+				// clip rangeLength to the length of this span. Extend the rangeLength by one to include the terminator if
+				// it is in the span, and the end of the range abuts the terminator. That way the terminator will stay in the 
+				// last span.
+				var begRelativeIdx:int = begIdx - startOffset;
+				if (begRelativeIdx + rangeLength > leaf.textLength)
+					rangeLength = leaf.textLength - begRelativeIdx;
+				if (begRelativeIdx + rangeLength == leaf.textLength - 1 && (leaf is SpanElement) && SpanElement(leaf).hasParagraphTerminator)
+					++rangeLength;
+				
+				var elemToUpdate:FlowLeafElement
+				if (leaf is SpanElement)
+					elemToUpdate = splitForChange(SpanElement(leaf),begIdx,rangeLength);
+				else
+				{
+					CONFIG::debug { assert(rangeLength >= leaf.textLength,"unable to split non-span leaf"); }
+					elemToUpdate = leaf;
+				}
+				
+				if (format is ITextLayoutFormat)
+					elemToUpdate.format = ITextLayoutFormat(format);
+				else
+					elemToUpdate.setCoreStylesInternal(format);
+				
+				return begIdx+rangeLength;
+			}
+			
+			rangeLength = leaf.textLength;
+			return startOffset+rangeLength;
+		}
+		
+		public static function applyTextStyleChange(flowRoot:TextFlow,begChange:int,endChange:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
+		{	
+			// TODO: this code only works for span's.  Revisit when new FlowLeafElement types enabled
+			var workIdx:int = begChange;
+			while (workIdx < endChange)
+			{
+				var elem:FlowLeafElement = flowRoot.findLeaf(workIdx);
+				CONFIG::debug  { assert(elem != null,"null FlowLeafElement found"); }
+				workIdx = applyCharacterFormat(elem,workIdx,endChange-workIdx,applyFormat,undefineFormat); 
+			}
+		}
+		
+		// used for undo of operation
+		public static function setTextStyleChange(flowRoot:TextFlow,begChange:int, endChange:int, coreStyle:Object):void
+		{
+			// TODO: this code only works for span's.  Revisit when new FlowLeafElement types enabled
+			var workIdx:int = begChange;
+			while (workIdx < endChange)
+			{
+				var elem:FlowElement = flowRoot.findLeaf(workIdx);
+				CONFIG::debug  { assert(elem != null,"null FlowLeafElement found"); }
+				workIdx = setCharacterFormat(FlowLeafElement(elem),coreStyle,workIdx,endChange-workIdx);
+			}
+		}
+
+		public static function splitParagraph(para:ParagraphElement, paraSplitPos:int, pointFormat:ITextLayoutFormat=null):ParagraphElement
+		{
+			CONFIG::debug { assert(((paraSplitPos >= 0) && (paraSplitPos <= para.textLength - 1)), "Invalid call to ParaEdit.splitParagraph"); }
+
+			var newPar:ParagraphElement;
+			var paraStartAbsolute:int = para.getAbsoluteStart();
+			var absSplitPos:int = paraStartAbsolute + paraSplitPos;
+			
+			if ((paraSplitPos == para.textLength - 1))
+			{
+				newPar = para.shallowCopy() as ParagraphElement;
+				newPar.replaceChildren(0, 0, new SpanElement());
+				var startIdx:int = para.parent.getChildIndex(para);
+				para.parent.replaceChildren(startIdx + 1, startIdx + 1, newPar);
+				if (newPar.textLength == 1)
+				{
+					//we have an empty paragraph.  Make sure that the first
+					//span of this paragraph has the same character attributes
+					//of the last span of this
+
+					var lastSpan:FlowLeafElement = para.getLastLeaf();
+					var prevSpan:FlowLeafElement;
+					if (lastSpan != null && lastSpan.textLength == 1)
+					{
+						//if the lastSpan is only a newline, you really want the span right before
+						var elementIdx:int = lastSpan.parent.getChildIndex(lastSpan);
+						if (elementIdx > 0)
+						{
+							prevSpan = lastSpan.parent.getChildAt(elementIdx - 1) as SpanElement;
+							if (prevSpan != null) lastSpan = prevSpan;
+						}
+					}
+					if (lastSpan != null)
+					{
+						ParaEdit.setTextStyleChange(para.getTextFlow(), absSplitPos + 1, absSplitPos + 2, lastSpan.format);
+					}
+					if (pointFormat != null)
+						ParaEdit.applyTextStyleChange(para.getTextFlow(),absSplitPos + 1, absSplitPos + 2, pointFormat, null);
+				}							
+			}
+			else
+			{
+				newPar = para.splitAtPosition(paraSplitPos) as ParagraphElement;
+			}
+			
+			//you can't have empty paragraphs.  Put the span back
+			// This now handled in normalize()
+			if (para.numChildren == 0)
+			{
+				//If we are injecting a new Span, we need to clone the attributes from 
+				//the newPar's first child.  If we don't, then contents of para will have
+				//no formatting. (2464521)
+				var newFormattedSpan:SpanElement = new SpanElement();
+				newFormattedSpan.quickCloneTextLayoutFormat(newPar.getChildAt(0));
+				para.replaceChildren(0, 0, newFormattedSpan);
+			}
+			
+			return newPar;
+		}
+		
+		// TODO: rewrite this method by moving the elements.  This is buggy.
+		public static function mergeParagraphWithNext(para:ParagraphElement):Boolean
+		{
+			var indexOfPara:int = para.parent.getChildIndex(para);
+			
+			// last can't merge
+			if (indexOfPara == para.parent.numChildren-1)
+				return false;
+				
+			var nextPar:ParagraphElement  = para.parent.getChildAt(indexOfPara + 1) as ParagraphElement;
+			// next is not a paragraph
+			if (nextPar == null)
+				return false;
+				
+			// remove nextPar from its parent - do this first because it will require less updating of starts and lengths
+			para.parent.replaceChildren(indexOfPara+1,indexOfPara+2,null);
+			if (nextPar.textLength <= 1) 
+				return true;
+			
+			// move all the elements
+			while (nextPar.numChildren)
+			{
+				var elem:FlowElement = nextPar.getChildAt(0);
+				nextPar.replaceChildren(0,1,null);
+				para.replaceChildren(para.numChildren,para.numChildren,elem);
+				if ((para.numChildren >  1) && (para.getChildAt(para.numChildren - 2).textLength == 0))
+				{
+					//bug 1658164
+					//imagine that the last element of para is only a kParaTerminator (like a single
+					//span of length 1 that only contains a kParaTerminator, and you merge with the
+					//next paragraph. That kParaTerminator will move, leaving an empty leaf element
+					para.replaceChildren(para.numChildren - 2, para.numChildren - 1, null);
+				}
+			}
+
+			return true;
+		}
+		
+		public static function cacheParagraphStyleInformation(flowRoot:TextFlow,begSel:int,endSel:int,undoArray:Array):void
+		{
+			while (begSel <= endSel && begSel >= 0)
+			{
+				var para:ParagraphElement = flowRoot.findLeaf(begSel).getParagraph();
+				
+				// build an object holding the old style and format
+				var obj:Object = new Object();
+				obj.begIdx = para.getAbsoluteStart();
+				obj.endIdx = obj.begIdx + para.textLength - 1;
+				obj.attributes = para.coreStyles;
+				undoArray.push(obj);
+
+				begSel = obj.begIdx + para.textLength;
+			}
+		}
+
+		/**
+		 * Replace the existing paragraph attributes with the incoming attributes.
+		 * 
+		 * @param flowRoot	text flow where paragraphs are
+		 * @param format	attributes to apply
+		 * @param beginIndex	text index within the first paragraph in the range
+		 * @param endIndex		text index within the last paragraph in the range
+		 */
+		// used for undo of operation
+		public static function setParagraphStyleChange(flowRoot:TextFlow,begChange:int, endChange:int, coreStyles:Object):void
+		{
+			var beginPara:int = begChange;
+			while (beginPara < endChange)
+			{
+				var para:ParagraphElement = flowRoot.findLeaf(beginPara).getParagraph();
+				
+				para.setCoreStylesInternal(coreStyles);
+				beginPara = para.getAbsoluteStart() + para.textLength;
+			}
+		}
+		
+		/**
+		 * Additively apply the paragraph formating attributes to the paragraphs in the specified range.
+		 * Each non-null field in the incoming format is copied into the existing paragraph attributes.
+		 * 
+		 * @param flowRoot	text flow where paragraphs are
+		 * @param format	attributes to apply
+		 * @param beginIndex	text index within the first paragraph in the range
+		 * @param endIndex		text index within the last paragraph in the range
+		 */
+		public static function applyParagraphStyleChange(flowRoot:TextFlow,begChange:int,endChange:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
+		{	
+			var curIndex:int = begChange;
+			while (curIndex <= endChange)
+			{
+				var para:ParagraphElement = flowRoot.findLeaf(curIndex).getParagraph();
+				
+				// now, need to get the change from "format" and apply to para. We make
+				// a new ParagraphFormat object instead of changing the ParagraphFormat
+				// already in the paragraph so that if the object is shared, other uses
+				// in other paragraphs will not be affected.
+				var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(para.format);
+				if (applyFormat)
+					newFormat.apply(applyFormat);
+				undefineDefinedFormats(newFormat,undefineFormat);
+				para.format = newFormat;
+				
+				curIndex = para.getAbsoluteStart() + para.textLength;
+			}		
+		}
+
+		public static function cacheStyleInformation(flowRoot:TextFlow,begSel:int,endSel:int,undoArray:Array):void
+		{
+			var elem:FlowElement = flowRoot.findLeaf(begSel);
+			var elemLength:int = elem.getAbsoluteStart()+elem.textLength-begSel;
+			var countRemaining:int = endSel - begSel;
+			CONFIG::debug { assert(countRemaining != 0,"cacheStyleInformation called on point selection"); }
+			for (;;)
+			{
+				// build an object holding the old style and format
+				var obj:Object = new Object();
+
+				obj.begIdx = begSel;
+				var objLength:int = Math.min(countRemaining, elemLength);
+				obj.endIdx = begSel + objLength;
+				
+				// save just the styles
+				obj.style = elem.coreStyles;
+				undoArray.push(obj);
+				
+				countRemaining -= Math.min(countRemaining, elemLength);
+				if (countRemaining == 0)
+					break;
+				
+				// advance
+				begSel = obj.endIdx;
+				
+				elem = flowRoot.findLeaf(begSel);
+				elemLength = elem.textLength;
+			}
+		}
+		
+		public static function cacheContainerStyleInformation(flowRoot:TextFlow,begIdx:int,endIdx:int,undoArray:Array):void
+		{
+			CONFIG::debug { assert(begIdx <= endIdx,"bad indexeds passed to ParaEdit.cacheContainerStyleInformation");  }
+			if (flowRoot.flowComposer)
+			{
+				var controllerIndex:int = flowRoot.flowComposer.findControllerIndexAtPosition(begIdx,false);
+				if (controllerIndex >= 0)
+				{
+					while (controllerIndex < flowRoot.flowComposer.numControllers)
+					{
+						var controller:ContainerController = flowRoot.flowComposer.getControllerAt(controllerIndex);
+						if (controller.absoluteStart >= endIdx)
+							break;
+						var obj:Object = new Object();
+						obj.container = controller;
+						// save just the styles
+						obj.attributes = controller.coreStyles;
+						undoArray.push(obj);
+						controllerIndex++;
+					}
+				}
+			}
+		}
+
+		public static function applyContainerStyleChange(flowRoot:TextFlow,begIdx:int,endIdx:int,applyFormat:ITextLayoutFormat,undefineFormat:ITextLayoutFormat):void
+		{
+			CONFIG::debug { assert(begIdx <= endIdx,"bad indexes passed to ParaEdit.cacheContainerStyleInformation");  }
+			if (flowRoot.flowComposer)
+			{
+				var controllerIndex:int = flowRoot.flowComposer.findControllerIndexAtPosition(begIdx,false);
+				if (controllerIndex >= 0)
+				{
+					while (controllerIndex < flowRoot.flowComposer.numControllers)
+					{
+						var controller:ContainerController = flowRoot.flowComposer.getControllerAt(controllerIndex);
+						if (controller.absoluteStart >= endIdx)
+							break;
+						var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(controller.format);
+						if (applyFormat)
+							newFormat.apply(applyFormat);
+						undefineDefinedFormats(newFormat,undefineFormat);
+						controller.format = newFormat;
+						controllerIndex++;
+					}
+				}
+			}
+		}
+
+		/** obj is created by cacheContainerStyleInformation */
+		public static function setContainerStyleChange(flowRoot:TextFlow,obj:Object):void
+		{
+			obj.container.format = obj.attributes as ITextLayoutFormat;
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/SelectionFormatState.as b/textLayout_edit/src/flashx/textLayout/edit/SelectionFormatState.as
new file mode 100755
index 0000000..6129843
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/SelectionFormatState.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout.edit
+{
+	[ExcludeClass]
+	/**
+	 *  Values for the selection background state
+	 *
+	 *  @see text.edit.SelectionFormat
+	 */
+ 	public final class SelectionFormatState 
+ 	{
+		/** default selection format state */
+    	public static const FOCUSED:String = "focused";
+    
+		/** selection state when selection doesn't have focus */    
+    	public static const UNFOCUSED:String = "unfocused";
+    
+		/** selection state when SelectionManager is inactive */        
+    	public static const INACTIVE:String = "inactive";
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/SelectionManager.as b/textLayout_edit/src/flashx/textLayout/edit/SelectionManager.as
new file mode 100755
index 0000000..7eb003f
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/SelectionManager.as
@@ -0,0 +1,2043 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.desktop.Clipboard;
+	import flash.desktop.ClipboardFormats;
+	import flash.display.DisplayObject;
+	import flash.display.InteractiveObject;
+	import flash.display.Stage;
+	import flash.errors.IllegalOperationError;
+	import flash.events.ContextMenuEvent;
+	import flash.events.Event;
+	import flash.events.FocusEvent;
+	import flash.events.IMEEvent;
+	import flash.events.KeyboardEvent;
+	import flash.events.MouseEvent;
+	import flash.events.TextEvent;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextLineValidity;
+	import flash.text.engine.TextRotation;
+	import flash.ui.ContextMenu;
+	import flash.ui.Keyboard;
+	import flash.ui.Mouse;
+	import flash.ui.MouseCursor;
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ColumnState;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.debug.Debugging;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.GlobalSettings;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.events.FlowOperationEvent;
+	import flashx.textLayout.events.SelectionEvent;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Category;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.operations.CopyOperation;
+	import flashx.textLayout.operations.FlowOperation;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.utils.NavigationUtil;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * The SelectionManager class manages text selection in a text flow.
+	 * 
+	 * <p>The selection manager keeps track of the selected text range, manages its formatting, 
+	 * and can handle events affecting the selection. To allow a user to make selections in
+	 * a text flow, assign a SelectionManager object to the <code>interactionManager</code>
+	 * property of the flow. (To allow editing, assign an instance of the EditManager class,
+	 * which extends SelectionManager.)</p>
+	 *
+	 * <p>The following table describes how the SelectionManager class handles keyboard shortcuts:</p>
+	 *
+	 * <table class="innertable" width="100%">
+	 * <thead>
+	 * <tr><th></th><th></th><th align = "center">TB,LTR</th><th align = "right"></th><th></th><th align = "center">TB,RTL</th><th></th><th></th><th align = "center">TL,LTR</th><th></th><th></th><th align = "center">RL,RTL</th><th></th></tr>
+	 * <tr><th></th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th><th>none</th><th>ctrl</th><th>alt|ctrl+alt</th></tr>
+	 * </thead>
+	 * <tr><td>leftarrow</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td></tr>
+	 * <tr><td>uparrow</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td></tr>
+	 * <tr><td>rightarrow</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td><td>previousLine</td><td>startOfDocument</td><td>startOfParagraph</td></tr>
+	 * <tr><td>downarrow</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextLine</td><td>endOfDocument</td><td>endOfParagraph</td><td>nextCharacter</td><td>nextWord</td><td>nextWord</td><td>previousCharacter</td><td>previousWord</td><td>previousWord</td></tr>
+	 * <tr><td>home</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td><td>startOfLine</td><td>startOfDocument</td><td>startOfLine</td></tr>
+	 * <tr><td>end</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td><td>endOfLine</td><td>endOfDocument</td><td>endOfLine</td></tr>
+	 * <tr><td>pagedown</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td><td>nextPage</td></tr>
+	 * <tr><td>pageup</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td><td>previousPage</td></tr>
+	 * </table>
+	 *
+	 * <p><strong>Key:</strong>
+	 * <ul>
+	 *	<li>none = no modifier</li>
+	 *	<li>ctrl, shift, alt = modifiers</li>
+	 *	<li>alt-key and ctrl+alt-key are the same on all platforms (on some platforms alt-key does not get to TLF)</li>
+	 *	<li>shift key modifes to extend the active end of the selection in the specified manner</li>			
+	 *	<li>TB (top-to-bottom),RL (right-to-left) are textFlow level <code>blockProgression</code> settings</li>						
+	 * 	<li>LTR (left-to-right),RTL (right-to-left) are textFlow level <code>direction</code> settings</li>					
+	 *	<li>next and prev in logical order in the textFlow - the effect in RTL text is that the selection moves in the physical direction</li>
+	 * </ul></p>
+	 * 
+	 * @see EditManager
+	 * @see flashx.elements.TextFlow
+	 * 
+	 * @includeExample examples\SelectionManager_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public class SelectionManager implements ISelectionManager
+	{		
+		private var _focusedSelectionFormat:SelectionFormat;
+		private var _unfocusedSelectionFormat:SelectionFormat;
+		private var _inactiveSelectionFormat:SelectionFormat;
+		private var _selFormatState:String = SelectionFormatState.UNFOCUSED;
+		private var _isActive:Boolean;
+		
+		/** The TextFlow of the selection. */
+		private var _textFlow:TextFlow;
+		
+		// current range of selection
+		/** Anchor point of the current selection, as an index into the TextFlow. */
+		private var anchorMark:Mark;
+		/** Active end of the current selection, as an index into the TextFlow. */
+		private var activeMark:Mark;
+		
+		// used to save pending attributes at a point selection
+		private var _pointFormat:ITextLayoutFormat;
+		/** 
+		 * The format that will be applied to inserted text. 
+		 * 
+		 * TBD: pointFormat needs to be extended to remember user styles and "undefine" of formats from calls to IEditManager.undefineFormat with leafFormat values on a point selection.
+		 */
+		protected function get pointFormat():ITextLayoutFormat
+		{ return _pointFormat; }
+
+		
+		/** @private
+		 * Ignore the next text input event. This is needed because the player may send a text input event
+		 * following by a key down event when ctrl+key is entered. 
+		 */
+		protected var ignoreNextTextEvent:Boolean = false;
+		
+		/**
+		 *  @private
+		 *  For usability reasons, operations are sometimes grouped (merged) so they 
+		 *  can be undone together. Certain events, such as changing the selection, may make merging 
+		 *  inappropriate. This flag is used to keep track of when operation merging
+		 *  is appropriate.  This might need to be moved to SelectionManager later. I'm keeping it
+		 *  here for now since I'm unsure if other regular selection operations that we add can
+		 *  be undone.
+		 */
+		protected var allowOperationMerge:Boolean = false;
+		
+		private var _mouseOverSelectionArea:Boolean = false;	
+
+		CONFIG::debug 
+		{
+			protected var id:String;
+			static private var smCount:int = 0;
+		}
+		
+		/** 
+		 * 
+		 * Creates a SelectionManager object.
+		 * 
+		 * <p>Assign a SelectionManager object to the <code>interactionManager</code> property of
+		 * a text flow to enable text selection.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function SelectionManager()
+		{
+			_textFlow = null;
+			anchorMark = createMark();
+			activeMark = createMark();
+			_pointFormat = null;
+			_isActive = false;
+			CONFIG::debug 
+			{
+				this.id = smCount.toString();
+				smCount++;
+			}
+		}
+		/**
+		 * @copy ISelectionManager#getSelectionState()
+		 * 
+		 * @includeExample examples\SelectionManager_getSelectionState.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.SelectionState
+		 */
+		public function getSelectionState():SelectionState
+		{
+			return new SelectionState(_textFlow, anchorMark.position, activeMark.position, pointFormat);
+		}
+				
+		/**
+		 * @copy ISelectionManager#setSelectionState()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 * 
+		 * @see flashx.textLayout.edit.SelectionState
+		 */
+		public function setSelectionState(sel:SelectionState):void
+		{
+			internalSetSelection(sel.textFlow, sel.anchorPosition, sel.activePosition, sel.pointFormat);
+		}
+
+		/**
+		 *  @copy ISelectionManager#hasSelection()
+		 * 
+		 * @includeExample examples\SelectionManager_hasSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function hasSelection():Boolean
+		{ return anchorMark.position != -1; }
+
+		/** 
+		 *  @copy ISelectionManager#isRangeSelection()
+		 * 
+		 * @includeExample examples\SelectionManager_isRangeSelection.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */				
+		public function isRangeSelection():Boolean
+		{ return anchorMark.position != -1 && anchorMark.position != activeMark.position; }
+		
+		/**
+		 * The TextFlow object managed by this selection manager. 
+		 * 
+		 * <p>A selection manager manages a single text flow. A selection manager can also be
+		 * assigned to a text flow by setting the <code>interactionManager</code> property of the
+		 * TextFlow object.</p>
+		 * 
+		 * @see flashx.textLayout.elements.TextFlow#interactionManager
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+ 		 */
+		public function get textFlow():TextFlow
+		{
+			return _textFlow;
+		}
+		public function set textFlow(value:TextFlow):void
+		{
+			if (_textFlow != value)
+			{
+				if (_textFlow)
+					flushPendingOperations();
+				
+				clear();
+				
+				_textFlow = value;
+				
+				if (_textFlow && _textFlow.interactionManager != this)
+					_textFlow.interactionManager = this;
+			}
+		}  
+		
+		/**
+		 *  @copy ISelectionManager#editingMode
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.EditingMode
+		 */
+		 public function get editingMode():String
+		 {
+		 	return EditingMode.READ_SELECT;
+		 }				 
+		 
+		/** 
+		 *  @copy ISelectionManager#windowActive
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		 public function get windowActive():Boolean
+		 {
+		 	return _selFormatState != SelectionFormatState.INACTIVE;
+		 }
+		 
+		/** 
+		 *  @copy ISelectionManager#focused
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/
+		 public function get focused():Boolean
+		 {
+		 	return _selFormatState == SelectionFormatState.FOCUSED;
+		 }
+		 
+		/**
+		 *  @copy ISelectionManager#currentSelectionFormat
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.SelectionFormat
+		 */
+		 public function get currentSelectionFormat():SelectionFormat
+		 { 
+		 	if (_selFormatState == SelectionFormatState.UNFOCUSED)
+		 	{
+		 		return unfocusedSelectionFormat;
+		 	}
+		 	else if (_selFormatState == SelectionFormatState.INACTIVE)
+		 	{
+		 		return inactiveSelectionFormat;
+		 	}
+		 	return focusedSelectionFormat;
+		 }
+		 
+		/**
+		 *  @copy ISelectionManager#focusedSelectionFormat
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.SelectionFormat
+		 */
+		 public function set focusedSelectionFormat(val:SelectionFormat):void
+		 { 
+	 		_focusedSelectionFormat = val;
+		 	if (this._selFormatState == SelectionFormatState.FOCUSED)
+		 		refreshSelection();
+		 }
+		 
+		/**
+		 * @private - docs on setter
+		 */
+		 public function get focusedSelectionFormat():SelectionFormat
+		 { 
+		 	return _focusedSelectionFormat ? _focusedSelectionFormat : (_textFlow ? _textFlow.configuration.focusedSelectionFormat : null);
+		 }		 
+
+		/**
+		 *  @copy ISelectionManager#unfocusedSelectionFormat
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.SelectionFormat
+		 */
+		 public function set unfocusedSelectionFormat(val:SelectionFormat):void
+		 { 
+	 		_unfocusedSelectionFormat = val;
+	 		if (this._selFormatState == SelectionFormatState.UNFOCUSED)
+	 			refreshSelection();
+		 }		 	
+		 
+		/**
+		 *  @private - docs on setter
+		 */
+		 public function get unfocusedSelectionFormat():SelectionFormat
+		 { 
+		 	return _unfocusedSelectionFormat ? _unfocusedSelectionFormat : (_textFlow ? _textFlow.configuration.unfocusedSelectionFormat : null);
+		 }
+		 
+		/**
+		 *  @copy ISelectionManager#inactiveSelectionFormat
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.edit.SelectionFormat
+		 */
+		 public function set inactiveSelectionFormat(val:SelectionFormat):void
+		 { 
+	 		_inactiveSelectionFormat = val;
+	 		if (this._selFormatState == SelectionFormatState.INACTIVE)
+	 			refreshSelection();
+		 }		 	
+		 
+		/**
+		 * @private - docs on setter
+		 */
+		 public function get inactiveSelectionFormat():SelectionFormat
+		 { 
+		 	return _inactiveSelectionFormat ? _inactiveSelectionFormat : (_textFlow ? _textFlow.configuration.inactiveSelectionFormat : null);
+		 }		 
+		 
+		 /** @private - returns the selectionFormatState.  @see flashx.textLayout.edit.SelectionFormatState */
+		 tlf_internal function get selectionFormatState():String
+		 { return _selFormatState; }
+		 
+		 /** @private - sets the SelectionFormatState. @see flashx.textLayout.edit.SelectionFormatState */
+		 tlf_internal function setSelectionFormatState(selFormatState:String):void
+		 {
+		 	if (selFormatState != _selFormatState)
+		 	{		 			
+		 	//	trace("changing selection state: was", _selFormatState, "switching to", selFormatState, "on selectionManager", id);
+			 	var oldSelectionFormat:SelectionFormat = currentSelectionFormat;
+			 	_selFormatState = selFormatState;
+			 	var newSelectionFormat:SelectionFormat = currentSelectionFormat;
+			 	if (!newSelectionFormat.equals(oldSelectionFormat))
+			 	{
+			 		refreshSelection();
+			 	}
+			 }
+		 }
+		 
+		 /** @private */
+		 tlf_internal function cloneSelectionFormatState(oldISelectionManager:ISelectionManager):void
+		 {
+			var oldSelectionManager:SelectionManager = oldISelectionManager as SelectionManager;
+			if (oldSelectionManager)
+			{
+				_isActive = oldSelectionManager._isActive;
+				_mouseOverSelectionArea = oldSelectionManager._mouseOverSelectionArea;
+				setSelectionFormatState(oldSelectionManager.selectionFormatState);
+			}
+		 }
+		 
+		/**
+		 * Gets the SelectionState at the specified mouse position.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @see flashx.textLayout.edit.SelectionState
+		 * @param currentTarget		The object that is actively processing the Event object with an event listener.
+		 * @param target			The InteractiveObject instance under the pointing device. The target is not always the object in the display list that registered the event listener. Use the currentTarget property to access the object in the display list that is currently processing the event.
+		 * @param localX			The horizontal coordinate at which the event occurred relative to the containing sprite.
+		 * @param localY			The vertical coordinate at which the event occurred relative to the containing sprite.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return the resulting SelectionState
+		 */		 		 		 		 		 		 		 		 		 		 		 		 		 		 
+		 private function selectionPoint(currentTarget:Object, target:InteractiveObject, localX:Number, localY:Number, extendSelection:Boolean = false):SelectionState
+		 {
+		 	//trace("selectionPoint");
+		 	if (!_textFlow) 
+		 		return null;
+		 	if (!hasSelection()) 
+		 		extendSelection = false;
+		 	
+			var begIdx:int = anchorMark.position;
+			var endIdx:int = activeMark.position;
+		 	
+			endIdx = computeSelectionIndex(_textFlow, target, currentTarget, localX, localY);
+			if (endIdx == -1)
+				return null;	// ignore
+			
+			// attempt to position in the logical hierarchy
+			var leaf:FlowLeafElement = _textFlow.findLeaf(endIdx);
+			
+			// make sure we aren't selecting after the paragraph terminating character
+			var para:ParagraphElement = leaf.getParagraph();
+			if (endIdx == para.getAbsoluteStart() + para.textLength)
+				endIdx--;
+				
+			if (!extendSelection)
+				begIdx = endIdx;							
+
+			if (begIdx == endIdx)
+			{
+				if (leaf is InlineGraphicElement) {
+					endIdx++;
+				}
+				begIdx = NavigationUtil.updateStartIfInReadOnlyElement(_textFlow, begIdx);
+				endIdx = NavigationUtil.updateEndIfInReadOnlyElement(_textFlow, endIdx);
+			} else {
+				endIdx = NavigationUtil.updateEndIfInReadOnlyElement(_textFlow, endIdx);
+			}			
+		 	return new SelectionState(textFlow, begIdx, endIdx);
+		 }		 		 		 
+		 
+		/** 
+		 *  @copy ISelectionManager#setFocus()
+		 * 
+		 * @includeExample examples\SelectionManager_setFocus.as -noswf
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/
+		 public function setFocus():void
+		 {
+			if (hasSelection())
+		 	{
+			 //	trace("setFocus sm", id);
+
+		 		// container with the activePosition gets the key focus
+		 		if (_textFlow.flowComposer)
+		 			_textFlow.flowComposer.setFocus(activePosition,false);
+		 		setSelectionFormatState(SelectionFormatState.FOCUSED);
+		 	}
+		 }
+		 
+		/**
+		 *  @copy ISelectionManager#anchorPosition
+		 */
+		public function get anchorPosition() : int
+		{
+			return anchorMark.position;
+		}
+		/**
+		 *  @copy ISelectionManager#activePosition
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function get activePosition() : int
+		{
+			return activeMark.position;			
+		}
+		/**
+		 *  @copy ISelectionManager#absoluteStart
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function get absoluteStart() : int
+		{
+			return (anchorMark.position < activeMark.position) ? anchorMark.position : activeMark.position;
+		}
+		/**
+		 *  @copy ISelectionManager#absoluteEnd
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function get absoluteEnd() : int
+		{
+			return (anchorMark.position > activeMark.position) ? anchorMark.position : activeMark.position;
+		}
+		
+		/** 
+		 *  @copy ISelectionManager#selectAll
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectAll() : void
+		{
+			selectRange(0, int.MAX_VALUE);
+		}
+		
+		/** 
+		 *  @copy ISelectionManager#selectRange
+		 * 
+		 * @includeExample examples\SelectionManager_selectRange.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+ 	 	 * 
+		 * @see flashx.textLayout.compose.IFlowComposer
+		 */
+		public function selectRange(anchorPosition:int, activePosition:int) : void
+		{
+			flushPendingOperations();
+			
+			// anchor and active can be in any order
+			// TODO: range check and clamp anchor,active
+			if (anchorPosition != anchorMark.position || activePosition != activeMark.position)
+			{	
+				clearSelectionShapes();
+					
+				internalSetSelection(_textFlow, anchorPosition, activePosition);
+				
+				// selection changed
+				selectionChanged();		
+				
+				allowOperationMerge = false;
+			}
+		}
+		
+		private function internalSetSelection(root:TextFlow,anchorPosition:int,activePosition:int,format:ITextLayoutFormat = null) : void
+		{
+			_textFlow = root;
+			
+			// clamp anchor/active
+			if (anchorPosition < 0 || activePosition < 0)
+			{
+				anchorPosition = -1;
+				activePosition = -1;
+			}
+			
+			if (anchorPosition != -1 && activePosition != -1)
+			{
+				if (anchorPosition >= _textFlow.textLength)
+					anchorPosition = _textFlow.textLength - 1;
+				
+				if (activePosition >= _textFlow.textLength)
+					activePosition = _textFlow.textLength - 1;
+			}
+
+			_pointFormat = format;
+			anchorMark.position = anchorPosition; // NavigationUtil.updateStartIfInReadOnlyElement(root, anchorPosition);
+			activeMark.position = activePosition; // NavigationUtil.updateEndIfInReadOnlyElement(root, activePosition);
+		//	trace("Selection ", anchorMark, "to", activeMark.position);
+		}		
+		
+		/** Clear any active selections.
+		 */
+		private function clear(): void
+		{
+			if (hasSelection())
+			{
+				flushPendingOperations();
+				clearSelectionShapes();
+				internalSetSelection(_textFlow, -1, -1);
+				// selection cleared
+				selectionChanged();
+				allowOperationMerge = false;
+			}
+		}
+		
+		private function addSelectionShapes():void
+		{
+			var blinking:Boolean = (currentSelectionFormat.pointBlinkRate != 0);
+			if (_textFlow.flowComposer && (blinking || (!blinking && (activeMark.position != anchorMark.position))))
+			{
+				// zero alpha means nothing is drawn so skip it
+				if (currentSelectionFormat && 
+					(((absoluteStart == absoluteEnd) &&  (currentSelectionFormat.pointAlpha != 0)) ||
+					 ((absoluteStart != absoluteEnd) && (currentSelectionFormat.rangeAlpha != 0))))
+				{
+					var containerIter:int = 0;
+					while(containerIter < _textFlow.flowComposer.numControllers)
+					{
+						_textFlow.flowComposer.getControllerAt(containerIter++).addSelectionShapes(currentSelectionFormat, absoluteStart, absoluteEnd);
+					}
+				} 
+			}
+		}
+		
+		private function clearSelectionShapes():void
+		{
+			if (_textFlow.flowComposer)
+			{
+				var containerIter:int = 0;
+				while(containerIter < _textFlow.flowComposer.numControllers)
+				{
+					_textFlow.flowComposer.getControllerAt(containerIter++).clearSelectionShapes();
+				}
+			}
+		}
+		
+		/** 
+		 *  @copy ISelectionManager#refreshSelection()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/
+		public function refreshSelection(): void
+		{
+			if (hasSelection())
+			{
+				clearSelectionShapes();
+				addSelectionShapes();
+			}
+		}
+		
+		/** Verifies that the selection is in a legal state. @private */
+		CONFIG::debug public function debugCheckSelectionManager():int
+		{
+			var rslt:int = 0;
+			if (hasSelection())
+			{
+				// both points must be within the flow - may not include trailing \n in final paragraph
+				rslt+= assert(anchorMark.position >= 0 && anchorMark.position < _textFlow.textLength,"SelectionManager:validate selBegIdx is out of range");
+				rslt += assert(activeMark.position >= 0 && activeMark.position < _textFlow.textLength,"SelectionManager:validate selEndIdx is out of range");
+			}
+			return rslt;
+		}
+		
+		// ////////////////////////////////////
+		// internal selection handling methods
+		// ////////////////////////////////////
+		
+		/** @private
+		 * Handler function called when the selection has been changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * @param doDispatchEvent	true if a selection changed event will be sent
+		 * @param resetPointFormat	true if the attributes associated with the caret should be discarded
+		 */
+		tlf_internal function selectionChanged(doDispatchEvent:Boolean = true, resetPointFormat:Boolean=true):void
+		{
+			CONFIG::debug { debugCheckSelectionManager(); }	// validates the selection
+			
+			// clear any remembered attributes for the next character
+			if (resetPointFormat) 
+				_pointFormat = null;
+			
+			if (doDispatchEvent)
+				textFlow.dispatchEvent(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, hasSelection() ? getSelectionState() : null));
+		}
+
+		// TODO: this routine could be much more efficient - instead of iterating over all lines in the TextFlow it should iterate over 
+		// the visible lines in the container.  Todo that move this routine into ContainerController and use the shapeChildren along with the logic in fillShapeChildren
+		static private function computeSelectionIndexInContainer(textFlow:TextFlow, controller:ContainerController, localX:Number, localY:Number):int
+		{
+			//var origX:Number = localX;
+			//var origY:Number = localY;
+			var lineIndex:int = -1;
+			
+			var firstCharVisible:int = controller.absoluteStart;
+			var length:int  = controller.textLength;
+			
+			// try to find a point on the line
+			var bp:String = textFlow.computedFormat.blockProgression;
+			var isTTB:Boolean = (bp == BlockProgression.RL);
+			var isDirectionRTL:Boolean = (textFlow.computedFormat.direction == Direction.RTL);
+			
+			//Establish perpendicular the coordinate for use with TTB or LTR/RTL lines
+			var perpCoor:Number = isTTB ? localX : localY;
+			
+			//get the nearest column so we can ignore lines which aren't in the column we're looking for.
+			//if we don't do this, we won't be able to select across column boundaries.
+			var nearestColIdx:int = locateNearestColumn(controller, localX, localY, textFlow.computedFormat.blockProgression,textFlow.computedFormat.direction);
+			
+			var prevLineBounds:Rectangle = null;
+			var previousLineIndex:int = -1;
+			
+			var lastLineIndexInColumn:int = -1;
+			
+			// Matching TextFlowLine and TextLine - they are not necessarily valid
+			var rtline:TextFlowLine;
+			var rtTextLine:TextLine;
+			
+			for (var testIndex:int = textFlow.flowComposer.numLines - 1; testIndex >= 0; testIndex--)
+			{
+				rtline = textFlow.flowComposer.getLineAt(testIndex);
+				if (rtline.controller != controller || rtline.columnIndex != nearestColIdx)
+				{
+					// use last line in previous column
+					if (lastLineIndexInColumn != -1)
+					{
+						lineIndex = testIndex+1;
+						break;
+					}
+					continue;
+				}
+					
+				// is this line even displayed?
+				if (rtline.absoluteStart < firstCharVisible || rtline.absoluteStart >= firstCharVisible+length)
+					continue;
+				rtTextLine = rtline.getTextLine();
+				if (rtTextLine == null || rtTextLine.parent == null)
+					continue;
+				
+				if (lastLineIndexInColumn == -1)
+					lastLineIndexInColumn = testIndex;
+					
+				var bounds:Rectangle = rtTextLine.getBounds(DisplayObject(controller.container));
+				// trace(testIndex.toString(),":",bounds.toString());
+				
+				var linePerpCoor:Number = isTTB ? bounds.left : bounds.bottom;
+				var midPerpCoor:Number = -1;//will be a positive value if prevLineBounds is not null
+				
+				//if this is not the first test loop, use the prevLineBounds to find the mid-point between the current
+				//line, which will be logically up from the previous line - we're walking back-to-front
+				if(prevLineBounds)
+				{
+					//if it's ttb, use the right bounds (ie the top of the line)...
+					var prevPerpCoor:Number = (isTTB ? prevLineBounds.right : prevLineBounds.top);
+					//calculate the midpoint
+					midPerpCoor = (linePerpCoor + prevPerpCoor)/2;
+				}
+				
+				//if the current line is below the click, then this OR the previous line, is the line we're looking for
+				var isLineBelow:Boolean = (isTTB ? linePerpCoor > perpCoor : linePerpCoor < perpCoor);
+				if(isLineBelow || testIndex == 0)
+				{
+					//if we haven't calculated the midPerpCoor (-1), then this is the first loop and we want to use the 
+					//current line,. Otherwise, if the click's perpendicular coordinate is below the mid point between the current
+					//line or below it, then we want to use the line below (ie the previous line, but logically the one after the current)
+					var inPrevLine:Boolean = midPerpCoor != -1 && (isTTB ? perpCoor < midPerpCoor : perpCoor > midPerpCoor);
+					lineIndex = inPrevLine && testIndex != lastLineIndexInColumn ? testIndex+1 : testIndex;	
+					break;
+				}
+				else
+				{
+					//this line is below the click, so set the prevLineBounds to bounds of the current line and move on...
+					prevLineBounds = bounds;
+					previousLineIndex = testIndex;
+				}
+			}
+
+			if (lineIndex == -1)
+			{
+				lineIndex = previousLineIndex;
+				if (lineIndex == -1)
+					return -1;	// no lines in container
+			}	
+				
+			//Get a valid textLine -- check to make sure line is valid, regenerate if necessary, make sure it has correct container relative coordinates
+			var tfl:TextFlowLine = textFlow.flowComposer.getLineAt(lineIndex);
+			var textLine:TextLine = tfl.getTextLine(true);
+			
+			// adjust localX,localY to be relative to the textLine.  
+			// Can't use localToGlobal/globalToLocal because textLine may not be on the display list due to virtualization
+			// we may need to bring this back if textline's can be rotated or placed by any mechanism other than a translation
+			// but then we'll need to provisionally place a virtualized TextLine in its parent container
+			localX -= textLine.x;
+			localY -= textLine.y;
+			/* var localPoint:Point = DisplayObject(controller.container).localToGlobal(new Point(localX,localY));
+			localPoint = textLine.globalToLocal(localPoint);
+			localX = localPoint.x;
+			localY = localPoint.y; */
+			
+			var lastAtomRect:Rectangle = new Rectangle(0, 0, 0, 0);
+			var textFlowLine:TextFlowLine = TextFlowLine(textLine.userData);
+			var startOnNextLineIfNecessary:Boolean = false;
+			
+			if (isDirectionRTL) {
+				lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 1);
+			} else {
+				if ((textFlowLine.absoluteStart + textFlowLine.textLength) >= textFlowLine.paragraph.textLength) {
+					if (textLine.atomCount > 1) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 2);
+				} else {
+					var lastLinePosInPar:int = textFlowLine.absoluteStart + textFlowLine.textLength - 1;
+					var lastChar:String = textLine.textBlock.content.rawText.charAt(lastLinePosInPar);
+					if (lastChar == " ") {
+						if (textLine.atomCount > 1) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 2);
+					} else {
+						startOnNextLineIfNecessary = true;
+						if (textLine.atomCount > 0) lastAtomRect = textLine.getAtomBounds(textLine.atomCount - 1);
+					}
+				}
+			}
+						
+			if (!isTTB)
+			{
+				if (localX < 0)
+					localX = 0;
+				else if (localX > (lastAtomRect.x + lastAtomRect.width))
+				{
+					if (startOnNextLineIfNecessary) 
+						return textFlowLine.absoluteStart + textFlowLine.textLength;
+					localX = lastAtomRect.x + lastAtomRect.width;
+				}
+			}
+			else
+			{	
+				if (localY < 0)
+					localY = 0;
+				else if (localY > (lastAtomRect.y + lastAtomRect.height))
+				{
+					if (startOnNextLineIfNecessary) 
+						return textFlowLine.absoluteStart + textFlowLine.textLength;			
+					localY = lastAtomRect.y + lastAtomRect.height;
+				}
+			}
+			
+			var result:int = computeSelectionIndexInLine(textFlow, textLine, localX, localY);
+			// trace("computeSelectionIndexInContainer:(",origX,origY,")",textFlow.flowComposer.getControllerIndex(controller).toString(),lineIndex.toString(),result.toString());
+			return result != -1 ? result : firstCharVisible + length;	
+		}
+		
+		static private function locateNearestColumn(container:ContainerController, localX:Number, localY:Number, wm:String, direction:String):int
+		{
+			var colIdx:int = 0;
+			//if we only have 1 column, no need to perform calculation...
+			var columnState:ColumnState = container.columnState;
+
+			//we need to compare the current column to the nextColmn
+			while(colIdx < columnState.columnCount - 1)
+			{
+				var curCol:Rectangle  = columnState.getColumnAt(colIdx);
+				var nextCol:Rectangle = columnState.getColumnAt(colIdx + 1);
+				
+				if(curCol.contains(localX, localY)) //in current column
+					break;
+				
+				if(nextCol.contains(localX, localY))//in next column
+				{
+					++colIdx;
+					break;
+				}
+				else
+				{
+					if(wm == BlockProgression.RL)
+					{
+						//if localY is above curCol || between columns, but close to current
+						if(localY < curCol.top || localY < nextCol.top && Math.abs(curCol.bottom - localY) <= Math.abs(nextCol.top - localY))
+							break;
+						
+						if(localY > nextCol.top)//between but closer to nextCol
+						{
+							++colIdx;
+							break;
+						}
+					}
+					else
+					{
+						if(direction  == Direction.LTR)
+						{
+							//if localX is left of curCol || between columns but closer to current, break here
+							if(localX < curCol.left || localX < nextCol.left && Math.abs(curCol.right - localX) <= Math.abs(nextCol.left - localX)) 
+								break;
+							if(localX < nextCol.left) // between, but closer to next column
+							{
+								++colIdx;
+								break;
+							}
+						}
+						else
+						{
+							//if localX is right of curCol || between columns, but closer to current
+							if(localX > curCol.right || localX > nextCol.right && Math.abs(curCol.left - localX) <= Math.abs(nextCol.right - localX))
+								break;
+							
+							if(localX > nextCol.right) // between, but closer to next column
+							{
+								++colIdx;
+								break;
+							}
+						} 
+					}
+				}
+				
+				//increment colIdx.  If this is the last pass through, then the conditions above were never met
+				//so we want the last column
+				++colIdx;
+			}
+
+			
+			return colIdx;
+		}
+		
+		static private function computeSelectionIndexInLine(textFlow:TextFlow, textLine:TextLine,localX:Number,localY:Number):int
+		{
+			if (!(textLine.userData is TextFlowLine))
+				return -1;	// not a TextLayout generated line
+				
+			var rtline:TextFlowLine = TextFlowLine(textLine.userData);
+			if (rtline.validity == TextLineValidity.INVALID)
+				return -1;	// not currently composed 
+			textLine = rtline.getTextLine(true);	// make sure the TextLine is not released
+			
+				
+			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
+			var perpCoor:Number = isTTB ? localX : localY;
+			
+			// new code for builds 385 and later
+			var pt:Point = new Point();
+			pt.x = localX;
+			pt.y = localY;
+			
+			// in most cases, we want to "fixup" the coordiates of the x and y coordinates
+			//because we could be getting a positive results for a click in the line, but the
+			//coordinates do not match any particular glyph.  However, there are cases where the 
+			//fix leads to bad results. For example, if there is a TCY run, this code will always cause
+			//a selection to be created in the middle of the run, meaning idividual glyphs cannot be selected.
+			//
+			//As a result, we need to be performing the less common case check prior to adjusting the 
+			//coordinates.
+			pt = textLine.localToGlobal(pt);
+			var elemIdx:int = textLine.getAtomIndexAtPoint(pt.x,pt.y);
+			//trace("global point: " + pt);
+			//trace("elemIdx: " + elemIdx);
+			if(elemIdx == -1)
+			{
+				//reset the pt
+				pt.x = localX;
+				pt.y = localY;
+				
+				//make adjustments
+				if (pt.x < 0 || (isTTB && perpCoor > textLine.ascent))
+					pt.x = 0;
+				if (pt.y < 0 || (!isTTB && perpCoor > textLine.descent))
+					pt.y = 0;
+				
+				//get the global again and get try for the element again
+				pt = textLine.localToGlobal(pt);
+				elemIdx = textLine.getAtomIndexAtPoint(pt.x,pt.y);
+				//trace("global point (second): " + pt);
+				//trace("elemIdx (second): " + elemIdx);
+			}
+			
+			//now we REALLY don't have a glyph, so return the head or tail of the line.
+			if (elemIdx == -1)
+			{
+				//we need to use global coordinates here.  reset pt and get conversion...
+				pt.x = localX;
+				pt.y = localY;
+				pt = textLine.localToGlobal(pt)
+				
+				if(!isTTB)
+					return (pt.x <= textLine.x) ? rtline.absoluteStart : (rtline.absoluteStart + rtline.textLength - 1);
+				else
+					return (pt.y <= textLine.y) ? rtline.absoluteStart : (rtline.absoluteStart + rtline.textLength - 1);
+			}
+			
+			// get the character box and if check we are past the middle select past this character. 
+			var glyphRect:Rectangle = textLine.getAtomBounds(elemIdx);
+			// trace("idx",elemIdx,"x",glyphRect.x,"y",glyphRect.y,"width",glyphRect.width,"height",glyphRect.height,"localX",localX,"localY",localY,"textLine.x",textLine.x);
+			var leanRight:Boolean = false;
+			if(glyphRect)
+			{	
+				//if this is TTB and NOT TCY determine lean based on Y coordinates...
+				if(isTTB && textLine.getAtomTextRotation(elemIdx) != TextRotation.ROTATE_0)
+					leanRight = (localY > (glyphRect.y + glyphRect.height/2));
+				else //use X..
+					leanRight = (localX > (glyphRect.x + glyphRect.width/2));
+			}
+			
+			var paraSelectionIdx:int;
+			if ((textLine.getAtomBidiLevel(elemIdx) % 2) != 0) // Right to left case, right is "start" unicode
+				paraSelectionIdx = leanRight ? textLine.getAtomTextBlockBeginIndex(elemIdx) : textLine.getAtomTextBlockEndIndex(elemIdx);
+			else  // Left to right case, right is "end" unicode
+				paraSelectionIdx = leanRight ? textLine.getAtomTextBlockEndIndex(elemIdx) : textLine.getAtomTextBlockBeginIndex(elemIdx);
+
+			//we again need to do some fixup here.  Unfortunately, we don't have the index into the paragraph until
+			
+			return rtline.paragraph.getAbsoluteStart() + paraSelectionIdx;
+		}
+		
+		static private function checkForDisplayed(container:DisplayObject):Boolean
+		{
+			while (container)
+			{
+				if (!container.visible)
+					return false;
+				container = container.parent;
+				if (container is Stage)
+					return true;					
+			}
+			return false;	// not on the stage
+
+		}
+		/** @private - given a target and location compute the selectionIndex */
+		static tlf_internal function computeSelectionIndex(textFlow:TextFlow, target:Object, currentTarget:Object, localX:Number,localY:Number):int
+		{			
+			//trace("computeSelectionIndex");
+			var rslt:int = 0;
+			var containerPoint:Point; // scratch
+			
+			//Make sure that if the target is a line, that it is part of THIS textFlow and not another.  Can happen
+			//when holding down mouse and moving out of one flow and over another. Could also happen when moving over
+			//TextLines that are either non-TLF or generated from a factory. 
+			var useTargetedTextLine:Boolean = false;
+			if (target is TextLine)
+			{
+				var tfl:TextFlowLine = TextLine(target).userData as TextFlowLine;
+				if (tfl)
+				{
+					var para:ParagraphElement = tfl.paragraph;
+					if(para.getTextFlow() == textFlow)
+						useTargetedTextLine = true;
+				}
+			}
+			/* trace("got target class", target.toString(), "at (", localX, localY, ")");
+			trace("Mapping",localX,localY,"for",target);
+			containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
+			trace("... Global",containerPoint.x,containerPoint.y);
+			containerPoint = DisplayObject(currentTarget).globalToLocal(containerPoint);
+			trace("... container Local",containerPoint.x,containerPoint.y); */
+			
+			if (useTargetedTextLine)
+				rslt = computeSelectionIndexInLine(textFlow, TextLine(target), localX, localY);
+			else
+			{
+				var controller:ContainerController;
+				for (var idx:int = 0; idx < textFlow.flowComposer.numControllers; idx++)
+				{
+					var testController:ContainerController = textFlow.flowComposer.getControllerAt(idx); 
+					if (testController.container == target || testController.container == currentTarget)
+					{
+						controller = testController;
+						break;
+					}
+				}
+				if (controller)
+				{	
+					if (target != controller.container)
+					{
+						containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
+						containerPoint = DisplayObject(controller.container).globalToLocal(containerPoint);
+						localX = containerPoint.x;
+						localY = containerPoint.y;
+					}
+					rslt = computeSelectionIndexInContainer(textFlow, controller, localX, localY);			
+				} 
+				else 
+				{
+					//the point is someplace else on stage.  Map the target 
+					//to the textFlow.container.
+					CONFIG::debug { assert(textFlow.flowComposer && textFlow.flowComposer.numControllers,"computeSelectionIndex: invalid textFlow"); }
+					
+					
+					// result of the search
+					var controllerCandidate:ContainerController = null;
+					var candidateLocalX:Number;
+					var candidateLocalY:Number;
+					var relDistance:Number = Number.MAX_VALUE;
+					
+					for (var containerIndex:int = 0; containerIndex < textFlow.flowComposer.numControllers; containerIndex++)
+					{
+						var curContainerController:ContainerController = textFlow.flowComposer.getControllerAt(containerIndex);
+						
+						// displayed??
+						if (!checkForDisplayed(curContainerController.container as DisplayObject))
+							continue;
+
+						// handle measured containers??
+						var bounds:Rectangle = curContainerController.getContentBounds();
+						var containerWidth:Number = isNaN(curContainerController.compositionWidth) ? curContainerController.effectivePaddingLeft+bounds.width : curContainerController.compositionWidth;
+						var containerHeight:Number = isNaN(curContainerController.compositionHeight) ? curContainerController.effectivePaddingTop+bounds.height : curContainerController.compositionHeight;
+						
+						containerPoint = DisplayObject(target).localToGlobal(new Point(localX, localY));
+						containerPoint = DisplayObject(curContainerController.container).globalToLocal(containerPoint);
+						
+						// remove scrollRect effects for the distance test but add it back in for the result
+						var adjustX:Number = 0;
+						var adjustY:Number = 0;
+						
+						if (curContainerController.hasScrollRect)
+						{
+							containerPoint.x -= (adjustX = curContainerController.container.scrollRect.x);
+							containerPoint.y -= (adjustY = curContainerController.container.scrollRect.y);
+						}
+						
+						if ((containerPoint.x >= 0) && (containerPoint.x <= containerWidth) &&
+							(containerPoint.y >= 0) && (containerPoint.y <= containerHeight))
+						{
+							controllerCandidate = curContainerController;
+							candidateLocalX = containerPoint.x+adjustX;
+							candidateLocalY = containerPoint.y+adjustY;
+							break;
+						}
+						
+						// figure minimum distance of containerPoint to curContainerController - 8 cases
+						var relDistanceX:Number = 0;
+						var relDistanceY:Number = 0;
+
+						if (containerPoint.x < 0)
+						{
+							relDistanceX = containerPoint.x;
+							if (containerPoint.y < 0)
+								relDistanceY = containerPoint.y;
+							else if (containerPoint.y > containerHeight)
+								relDistanceY = containerPoint.y-containerHeight;
+						}
+						else if (containerPoint.x > containerWidth)
+						{
+							relDistanceX = containerPoint.x-containerWidth;
+							if (containerPoint.y < 0)
+								relDistanceY = containerPoint.y;
+							else if (containerPoint.y > containerHeight)
+								relDistanceY = containerPoint.y-containerHeight;
+						}
+						else if (containerPoint.y < 0)
+							relDistanceY = -containerPoint.y;
+						else
+							relDistanceY = containerPoint.y-containerHeight;
+						var tempDist:Number = relDistanceX*relDistanceX + relDistanceY*relDistanceY;	// could do sqrt but why bother - there is no Math.hypot function
+						if (tempDist <= relDistance)
+						{
+							relDistance = tempDist;
+							controllerCandidate = curContainerController;
+							candidateLocalX = containerPoint.x+adjustX;
+							candidateLocalY = containerPoint.y+adjustY;
+						}
+					}
+
+
+					rslt = controllerCandidate ? computeSelectionIndexInContainer(textFlow, controllerCandidate, candidateLocalX, candidateLocalY) : -1;
+				}
+			}
+			
+			if (rslt >= textFlow.textLength)
+				rslt = textFlow.textLength-1;
+			return rslt;
+		}
+		
+		/** initialize a new point selection at click point @private */
+		tlf_internal function setNewSelectionPoint(currentTarget:Object, target:InteractiveObject, localX:Number, localY:Number, extendSelection:Boolean = false):Boolean
+		{
+			var selState:SelectionState = selectionPoint(currentTarget, target, localX, localY, extendSelection);
+			if (selState == null)
+				return false;	// ignore
+			
+			if (selState.anchorPosition != anchorMark.position || selState.activePosition != activeMark.position)
+			{
+			//	clear(false);
+			//	internalSetSelection(_textFlow, selState.anchorPosition, selState.activePosition);
+				selectRange(selState.anchorPosition, selState.activePosition);
+				return true;
+			}
+			return false;
+		}
+		
+		// ///////////////////////////////////
+		// Mouse and keyboard methods 
+		// ///////////////////////////////////
+		
+		/** 
+		 *  @copy IInteractionEventHandler#mouseDownHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function mouseDownHandler(event:MouseEvent):void
+		{
+			handleMouseEventForSelection(event, event.shiftKey);
+		}
+		
+		/**
+		 * @copy IInteractionEventHandler#mouseMoveHandler()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function mouseMoveHandler(event:MouseEvent):void
+		{
+			var wmode:String = textFlow.computedFormat.blockProgression;			
+			if (wmode != BlockProgression.RL) 
+				Mouse.cursor = MouseCursor.IBEAM;			
+			if (event.buttonDown)
+				handleMouseEventForSelection(event, true);
+		}
+		
+		private function handleMouseEventForSelection(event:MouseEvent, allowExtend:Boolean):void
+		{
+			var startSelectionActive:Boolean = hasSelection();
+			
+			if (setNewSelectionPoint(event.currentTarget, event.target as InteractiveObject, event.localX, event.localY, startSelectionActive && allowExtend))
+			{
+				selectionChanged();
+				if (startSelectionActive)
+					clearSelectionShapes();
+
+				if (hasSelection())
+					addSelectionShapes();
+			}		
+			allowOperationMerge = false;
+		}
+		
+		/** 
+		 * @copy IInteractionEventHandler#mouseUpHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function mouseUpHandler(event:MouseEvent):void
+		{
+			if (!_mouseOverSelectionArea)
+			{
+				Mouse.cursor = MouseCursor.AUTO;
+			}
+		}
+		
+		private function atBeginningWordPos(activePara:ParagraphElement, pos:int):Boolean
+		{
+			if (pos == 0) return true;
+			var nextPos:int = activePara.findNextWordBoundary(pos);
+			nextPos = activePara.findPreviousWordBoundary(nextPos);
+			return (pos == nextPos);
+		}
+				
+		
+		/** 
+		 * @copy IInteractionEventHandler#mouseDoubleClickHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function mouseDoubleClickHandler(event:MouseEvent):void
+		{
+			if (!hasSelection())
+				return;
+
+			// We got a previous single click event that set the selection.
+			// Extend it into a selection for the entire word.
+
+			// Adjust the active end to the beginning or end of the nearest word, depending on which end of the selection is active
+			var activePara:ParagraphElement = _textFlow.findAbsoluteParagraph(activeMark.position);
+			var activeParaStart:int = activePara.getAbsoluteStart();
+			var newActiveIndex:int; // adjusted active index
+			if (anchorMark.position <= activeMark.position)
+				newActiveIndex = activePara.findNextWordBoundary(activeMark.position - activeParaStart) + activeParaStart;
+			else
+				newActiveIndex = activePara.findPreviousWordBoundary(activeMark.position - activeParaStart) + activeParaStart;
+				
+			// don't include end of paragraph marker
+			if (newActiveIndex == activeParaStart+activePara.textLength)
+				newActiveIndex--;
+
+			// Adjust the anchor end. If we're doing a dbl-click shift select to extend the selection, the anchor point stays the same.
+			// Otherwise adjust it to the beginning or end of the nearest word, depending on which end of the selection is active
+			var newAnchorIndex:int; // adjusted anchor index
+			if (event.shiftKey)	
+				newAnchorIndex = anchorMark.position;
+			else
+			{
+				var anchorPara:ParagraphElement = _textFlow.findAbsoluteParagraph(anchorMark.position);
+				var anchorParaStart:int = anchorPara.getAbsoluteStart();
+				if (atBeginningWordPos(anchorPara, anchorMark.position - anchorParaStart))
+				{
+					newAnchorIndex = anchorMark.position;					
+				}
+				else
+				{
+					if (anchorMark.position <= activeMark.position)
+						newAnchorIndex = anchorPara.findPreviousWordBoundary(anchorMark.position - anchorParaStart) + anchorParaStart;
+					else
+						newAnchorIndex = anchorPara.findNextWordBoundary(anchorMark.position - anchorParaStart) + anchorParaStart;
+					// don't include end of paragraph marker
+					if (newAnchorIndex == anchorParaStart+anchorPara.textLength)
+						newAnchorIndex--;
+				}	
+			}
+			
+			if (newAnchorIndex != anchorMark.position || newActiveIndex != activeMark.position)
+			{
+				internalSetSelection(_textFlow, newAnchorIndex, newActiveIndex, null);				
+				selectionChanged();
+				clearSelectionShapes();
+
+				if (hasSelection())
+					addSelectionShapes();
+			}
+			
+			allowOperationMerge = false;
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#mouseOverHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */							
+		public function mouseOverHandler(event:MouseEvent):void
+		{
+			_mouseOverSelectionArea = true;
+			var wmode:String = textFlow.computedFormat.blockProgression;
+			if (wmode != BlockProgression.RL) 
+				Mouse.cursor = MouseCursor.IBEAM;	
+			else 
+				Mouse.cursor = MouseCursor.AUTO;								
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#mouseOutHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */					
+		public function mouseOutHandler(event:MouseEvent):void
+		{
+			_mouseOverSelectionArea = false;			
+			Mouse.cursor = MouseCursor.AUTO;									
+		}		
+		
+		/** 
+		 * @copy IInteractionEventHandler#focusInHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function focusInHandler(event:FocusEvent):void
+		{			
+			// The focusIn can come before the activate. If so, we don't want the later activate to wipe out the focusIn
+			_isActive = true;	
+			
+			//trace("focusIn event on selectionManager", this.id);
+			setSelectionFormatState(SelectionFormatState.FOCUSED);		
+		}
+		 
+		/** 
+		 * @copy IInteractionEventHandler#focusOutHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function focusOutHandler(event:FocusEvent):void
+		{
+			//trace("focusOut event on selectionManager", this.id);
+			if (_isActive)	// don't do it if we aren't active
+				setSelectionFormatState(SelectionFormatState.UNFOCUSED);			
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#activateHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */				
+		public function activateHandler(event:Event):void
+		{
+			//trace("activate selectionManager", id);
+			// If there are multiple containers, the selection manager will get multiple activate & deactivate events,
+			// one per container. We only want to respond to the first one, because otherwise a focus event that comes
+			// in the middle will get its state change overwritten.
+			if (!_isActive)
+			{		
+				_isActive = true;
+				setSelectionFormatState(SelectionFormatState.UNFOCUSED);
+			}	
+		}
+		
+		/** 
+		 * @copy IInteractionEventHandler#deactivateHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */				
+		public function deactivateHandler(event:Event):void
+		{
+			//trace("deactivate selectionManager", id);
+			// If there are multiple containers, the selection manager will get multiple activate & deactivate events,
+			// one per container. We only want to respond to the first one, because otherwise a focus event that comes
+			// in the middle will get its state change overwritten.
+			if (_isActive)
+			{
+				_isActive = false;
+				setSelectionFormatState(SelectionFormatState.INACTIVE);			
+			}
+		}
+		
+		/** Perform a SelectionManager operation - these may never modify the flow but clients still are able to cancel them. 
+		  * 
+		  * @playerversion Flash 10
+		  * @playerversion AIR 1.5
+ 	 	  * @langversion 3.0
+		  */
+		public function doOperation(op:FlowOperation):void
+		{
+			var opEvent:FlowOperationEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN,false,true,op,0,null);
+			textFlow.dispatchEvent(opEvent);
+			if (!opEvent.isDefaultPrevented())
+			{
+				op = opEvent.operation;
+				
+				// only copy operation is allowed
+				if (!(op is CopyOperation))
+					throw new IllegalOperationError(GlobalSettings.resourceStringFunction("illegalOperation",[ getQualifiedClassName(op) ]));
+				var opError:Error = null;
+				try
+				{
+					op.doOperation();
+				}
+				catch(e:Error)
+				{
+					opError = e;
+				}
+				// operation completed - send event whether it succeeded or not.
+				opEvent = new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END,false,true,op,0,opError);
+				textFlow.dispatchEvent(opEvent);
+				opError = opEvent.isDefaultPrevented() ? null : opEvent.error;
+				if (opError)
+					throw (opError);
+				textFlow.dispatchEvent(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE,false,false,op,0,null));
+			}			
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#editHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 		 * @langversion 3.0
+		 */	
+		public function editHandler(event:Event):void
+		{
+			switch (event.type)
+			{
+				case Event.COPY:
+					flushPendingOperations();
+					doOperation(new CopyOperation(getSelectionState()));
+
+					break;
+				case Event.SELECT_ALL:
+					flushPendingOperations();
+					selectAll();
+					refreshSelection();
+					break;	
+			}
+			
+		}
+
+		private function handleLeftArrow(event:KeyboardEvent):SelectionState
+		{			
+			var selState:SelectionState = getSelectionState();
+			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
+			{
+				if(_textFlow.computedFormat.direction == Direction.LTR)
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.previousWord(selState,event.shiftKey);
+					else
+						NavigationUtil.previousCharacter(selState,event.shiftKey);
+				}
+				else
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.nextWord(selState,event.shiftKey);
+					else
+						NavigationUtil.nextCharacter(selState,event.shiftKey);
+				}
+			} 
+			else 
+			{
+				// always test for altkey first - that way ctrl-alt is the same as alt
+				if (event.altKey)
+					NavigationUtil.endOfParagraph(selState,event.shiftKey);
+				else if (event.ctrlKey)
+					NavigationUtil.endOfDocument(selState,event.shiftKey);
+				else
+					NavigationUtil.nextLine(selState,event.shiftKey);
+			}
+			return selState;
+		}
+		
+		private function handleUpArrow(event:KeyboardEvent):SelectionState
+		{			
+			var selState:SelectionState = getSelectionState();
+			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
+			{
+				// always test for altkey first - that way ctrl-alt is the same as alt
+				if (event.altKey)
+					NavigationUtil.startOfParagraph(selState,event.shiftKey);
+				else if (event.ctrlKey)
+					NavigationUtil.startOfDocument(selState,event.shiftKey);
+				else
+					NavigationUtil.previousLine(selState,event.shiftKey);
+			}
+			else
+			{
+				if(_textFlow.computedFormat.direction == Direction.LTR)
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.previousWord(selState,event.shiftKey);
+					else
+						NavigationUtil.previousCharacter(selState,event.shiftKey); 
+				}
+				else
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.nextWord(selState,event.shiftKey);
+					else
+						NavigationUtil.nextCharacter(selState,event.shiftKey);
+				}
+			}
+			return selState;
+		}
+		
+		private function handleRightArrow(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			
+		 	if(_textFlow.computedFormat.blockProgression  != BlockProgression.RL)
+		 	{
+		 		if(_textFlow.computedFormat.direction == Direction.LTR)
+		 		{
+			 		if (event.ctrlKey || event.altKey)
+			 			NavigationUtil.nextWord(selState,event.shiftKey);
+			 		else
+			 			NavigationUtil.nextCharacter(selState,event.shiftKey);
+			 	}
+			 	else
+			 	{
+			 		if (event.ctrlKey || event.altKey)
+						NavigationUtil.previousWord(selState,event.shiftKey);
+					else
+						NavigationUtil.previousCharacter(selState,event.shiftKey);
+			 	}
+		 	}
+		 	else
+		 	{
+				// always test for altkey first - that way ctrl-alt is the same as alt
+				if (event.altKey)
+					NavigationUtil.startOfParagraph(selState,event.shiftKey);
+				else if (event.ctrlKey)
+					NavigationUtil.startOfDocument(selState,event.shiftKey);
+				else
+					NavigationUtil.previousLine(selState,event.shiftKey);
+			}
+			return selState;
+		}
+		
+		private function handleDownArrow(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			
+			if(_textFlow.computedFormat.blockProgression != BlockProgression.RL)
+			{
+				// always test for altkey first - that way ctrl-alt is the same as alt
+				if (event.altKey)
+					NavigationUtil.endOfParagraph(selState,event.shiftKey);
+				else if (event.ctrlKey)
+					NavigationUtil.endOfDocument(selState,event.shiftKey);
+				else
+					NavigationUtil.nextLine(selState,event.shiftKey);
+			}
+			else
+			{
+				if(_textFlow.computedFormat.direction == Direction.LTR)
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.nextWord(selState,event.shiftKey);
+					else
+						NavigationUtil.nextCharacter(selState,event.shiftKey);
+				}
+				else
+				{
+					if (event.ctrlKey || event.altKey)
+						NavigationUtil.previousWord(selState,event.shiftKey);
+					else
+						NavigationUtil.previousCharacter(selState,event.shiftKey); 
+				}
+			}
+
+			return selState;
+		}
+		
+		private function handleHomeKey(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			if (event.ctrlKey && !event.altKey)
+				NavigationUtil.startOfDocument(selState,event.shiftKey);
+			else
+				NavigationUtil.startOfLine(selState,event.shiftKey);
+			return selState;
+		}
+		
+		private function handleEndKey(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			if (event.ctrlKey && !event.altKey)
+				NavigationUtil.endOfDocument(selState,event.shiftKey);
+			else
+				NavigationUtil.endOfLine(selState,event.shiftKey);
+			return selState;
+		}
+		
+		private function handlePageUpKey(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			NavigationUtil.previousPage(selState,event.shiftKey);
+			return selState;
+		}
+
+		private function handlePageDownKey(event:KeyboardEvent):SelectionState
+		{
+			var selState:SelectionState = getSelectionState();
+			NavigationUtil.nextPage(selState,event.shiftKey);
+			return selState;
+		}		
+						
+		private function handleKeyEvent(event:KeyboardEvent):void
+		{
+			var selState:SelectionState = null;
+			flushPendingOperations();			
+			
+			switch(event.keyCode)
+			{
+				case Keyboard.LEFT:
+					selState = handleLeftArrow(event);
+					break;
+				case Keyboard.UP:
+					selState = handleUpArrow(event);
+					break;
+				case Keyboard.RIGHT:
+					selState = handleRightArrow(event);
+					break;
+				case Keyboard.DOWN:
+					selState = handleDownArrow(event);
+					break;
+				case Keyboard.HOME:
+					selState = handleHomeKey(event);
+					break;
+				case Keyboard.END:
+					selState = handleEndKey(event);
+					break;
+				case Keyboard.PAGE_DOWN:
+					selState = handlePageDownKey(event);
+					break;
+				case Keyboard.PAGE_UP:
+					selState = handlePageUpKey(event);
+					break;
+			}
+
+			if (selState != null)
+			{
+				event.preventDefault();
+				updateSelectionAndShapes(_textFlow, selState.anchorPosition, selState.activePosition);
+
+				// make sure the active end is visible in the container -- scroll if necessary
+				if (_textFlow.flowComposer && _textFlow.flowComposer.numControllers != 0)
+					 _textFlow.flowComposer.getControllerAt(_textFlow.flowComposer.numControllers-1).scrollToRange(selState.activePosition,selState.activePosition);
+			}
+			allowOperationMerge = false;
+		}																										
+			
+		/** 
+		 * @copy IInteractionEventHandler#keyDownHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function keyDownHandler(event:KeyboardEvent):void
+		{
+			if (!hasSelection() || event.isDefaultPrevented())
+				return;
+
+			if (event.charCode == 0)
+			{	
+				// the keycodes that we currently handle
+				switch(event.keyCode)
+				{
+					case Keyboard.LEFT:
+					case Keyboard.UP:
+					case Keyboard.RIGHT:
+					case Keyboard.DOWN:
+					case Keyboard.HOME:
+					case Keyboard.END:
+					case Keyboard.PAGE_DOWN:
+					case Keyboard.PAGE_UP:
+					case Keyboard.ESCAPE:
+						handleKeyEvent(event);
+						break;
+				}
+			}
+			else if (event.keyCode == Keyboard.ESCAPE)
+				handleKeyEvent(event);
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#keyUpHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * 	@param	event	the keyUp event
+		 */			
+		public function keyUpHandler(event:KeyboardEvent):void
+		{
+			//do nothing here
+		}
+		
+		/** 
+		 * @copy IInteractionEventHandler#keyFocusChangeHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 * 	@param	event	the FocusChange event
+		 */	
+		public function keyFocusChangeHandler(event:FocusEvent):void
+		{
+			return;	// ignores manageTabKey if not editable
+		}	
+		
+		/** 
+		 * @copy IInteractionEventHandler#textInputHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/
+		public function textInputHandler(event:TextEvent):void
+		{
+			// do nothing
+			ignoreNextTextEvent = false;
+		}
+
+		/** 
+		 * @copy IInteractionEventHandler#imeStartCompositionHandler()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		*/
+		public function imeStartCompositionHandler(event:IMEEvent):void
+		{
+			// Do nothing -- this is handled in the EditManager if editing is supported
+			// If there is no EditManager, doing nothing will refuse the IME session.
+		}
+		
+		/**
+		 *  @private
+		 * 
+		 *  Execute asynchronous operations at the beginning of a frame. This
+		 *  event listener is called only if there is work that needs to be done.
+		 */
+		protected function enterFrameHandler(event:Event):void
+		{
+			flushPendingOperations();
+		}
+
+		/**
+		 * @copy IInteractionEventHandler#focusChangeHandler()
+		 */
+		public function focusChangeHandler(event:FocusEvent):void
+		{ }
+		
+		/**
+		 * @copy IInteractionEventHandler#menuSelectHandler()
+		 */
+		public function menuSelectHandler(event:ContextMenuEvent):void
+		{
+			var menu:ContextMenu = event.target as ContextMenu;
+			
+			if (activePosition != anchorPosition)
+			{
+				menu.clipboardItems.copy = true;
+				menu.clipboardItems.cut = editingMode == EditingMode.READ_WRITE;
+				menu.clipboardItems.clear = editingMode == EditingMode.READ_WRITE;
+			} else {
+				menu.clipboardItems.copy = false;
+				menu.clipboardItems.cut = false;
+				menu.clipboardItems.clear = false;
+			}
+			
+			var systemClipboard:Clipboard = Clipboard.generalClipboard;
+			if (activePosition != -1 && editingMode == EditingMode.READ_WRITE && (systemClipboard.hasFormat(TextClipboard.TEXT_LAYOUT_MARKUP) || systemClipboard.hasFormat(ClipboardFormats.TEXT_FORMAT)))
+			{
+				menu.clipboardItems.paste = true;
+			} else {
+				menu.clipboardItems.paste = false;
+			}
+			menu.clipboardItems.selectAll = true;		
+		}
+		
+		/**
+		 * @copy IInteractionEventHandler#mouseWheelHandler()
+		 */
+		public function mouseWheelHandler(event:MouseEvent):void
+		{ }				
+		/**
+		 * @copy IInteractionEventHandler#flushPendingOperations()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function flushPendingOperations():void
+		{	}
+
+		/**
+		 * @copy ISelectionManager#getCommonCharacterFormat()
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonCharacterFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function getCommonCharacterFormat(range:TextRange=null):ITextLayoutFormat
+		{
+			if (!range && !hasSelection())
+				return null;
+			
+			var selRange:ElementRange = ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd);
+			
+			var leaf:FlowLeafElement = selRange.firstLeaf;
+			var attr:TextLayoutFormat = new TextLayoutFormat(leaf.computedFormat);
+	
+			// include any attributes set on a point selection but not yet applied	and return	
+			if (!isRangeSelection())
+			{
+				if (pointFormat)
+					attr.apply(pointFormat)
+			}
+			else
+			{
+				for (;;)
+				{
+					if (leaf == selRange.lastLeaf)
+						break;
+					leaf = leaf.getNextLeaf();
+					attr.removeClashing(leaf.computedFormat);
+				}
+			}
+			
+			return Property.extractInCategory(TextLayoutFormat, TextLayoutFormat.description, attr, Category.CHARACTER) as ITextLayoutFormat;
+		}
+		
+		 
+		 /**
+		 * @copy ISelectionManager#getCommonParagraphFormat()
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonParagraphFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function getCommonParagraphFormat (range:TextRange=null):ITextLayoutFormat
+		{
+			if (!range && !hasSelection())
+				return null;
+			
+			var selRange:ElementRange = ElementRange.createElementRange(_textFlow, range ? range.absoluteStart : absoluteStart, range? range.absoluteEnd : absoluteEnd);
+			
+			var para:ParagraphElement = selRange.firstParagraph;
+			var attr:TextLayoutFormat = new TextLayoutFormat(para.computedFormat);
+			for (;;)
+			{
+				if (para == selRange.lastParagraph)
+					break;
+				para = _textFlow.findAbsoluteParagraph(para.getAbsoluteStart()+para.textLength);
+				attr.removeClashing(para.computedFormat);
+			}
+			return Property.extractInCategory(TextLayoutFormat,TextLayoutFormat.description,attr,Category.PARAGRAPH) as ITextLayoutFormat;
+		 }
+		 
+		/**
+		 * @copy ISelectionManager#getCommonContainerFormat()
+		 * 
+		 * @includeExample examples\SelectionManager_getCommonContainerFormat.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function getCommonContainerFormat (range:TextRange=null):ITextLayoutFormat
+		{
+			if (!range && !hasSelection())
+				return null;
+			
+			// TODO: FIX THIS - tlf_core supports mulutiple containers
+		 	// container attributes changes through the UI apply to TextFlow and all containers 
+		 	// as of changelist# 625596, so all attributes values are 'common'.
+		 	// note: that's true of your UI but that's no guarantee of common - the API supports users doing direct modifications outside the UI
+		 	// need to revisit this when there are linked controllers
+		 	CONFIG::debug { assert(textFlow.flowComposer.numControllers  == 1,"multiple containers not supported by SelectionManager.getCommonContainerFormat"); }
+		 	return Property.extractInCategory(TextLayoutFormat,TextLayoutFormat.description,textFlow.flowComposer.getControllerAt(0).computedFormat,Category.CONTAINER) as ITextLayoutFormat;
+		}
+		 
+		/**
+		 * Refreshes and displays TextFlow selection defined by a beginning and ending index.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		private function updateSelectionAndShapes(tf:TextFlow, begIdx:int, endIdx:int):void
+		{
+			internalSetSelection(tf, begIdx, endIdx);
+			if (_textFlow.flowComposer && _textFlow.flowComposer.numControllers != 0)
+				_textFlow.flowComposer.getControllerAt(_textFlow.flowComposer.numControllers-1).scrollToRange(activeMark.position,anchorMark.position);
+				
+			selectionChanged();
+			clearSelectionShapes();
+			addSelectionShapes();
+		}
+		
+		/** @private */
+		CONFIG::debug tlf_internal function debugCheckTextFlow():int
+		{
+			if (flashx.textLayout.debug.Debugging.debugOn)
+				return _textFlow.debugCheckTextFlow();
+			return 0;
+		}
+		
+		private var marks:Array = [];
+		
+		/** @private */
+		tlf_internal function createMark():Mark
+		{
+			var mark:Mark = new Mark(-1);
+			marks.push(mark);
+			return mark;
+		}
+		/** @private */
+		tlf_internal function removeMark(mark:Mark):void
+		{
+			var idx:int = marks.indexOf(mark);
+			if (idx != -1)
+				marks.splice(idx,idx+1);
+		}
+		
+		/** 
+		 * @copy ISelectionManager#notifyInsertOrDelete()
+		 * 
+		 * @includeExample examples\SelectionManager_notifyInsertOrDelete.as -noswf
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function notifyInsertOrDelete(absolutePosition:int, length:int):void
+		{
+			if (length == 0)
+				return;
+			for (var i:int = 0; i < marks.length; i++)
+			{
+				var mark:Mark = marks[i];
+				if (mark.position >= absolutePosition)
+				{
+					if (length < 0)
+						mark.position = (mark.position + length < absolutePosition) ? absolutePosition : mark.position + length;
+					else
+						mark.position += length;
+				}
+			}
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/TextClipboard.as b/textLayout_edit/src/flashx/textLayout/edit/TextClipboard.as
new file mode 100755
index 0000000..8ec6133
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/TextClipboard.as
@@ -0,0 +1,366 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flash.desktop.Clipboard;
+	import flash.desktop.ClipboardFormats;
+	
+	import flashx.textLayout.conversion.*;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+
+	/**
+	 * The TextClipboard class copies and pastes TextScrap objects to and from the system clipboard.
+	 * 
+	 * <p>When you copy a TextScrap to the TextClipboard, the information is copied to the
+	 * system clipboard in two clipboard formats. One format is an XML string expressing the copied 
+	 * TextScrap object in Text Layout Markup syntax. This clipboard object uses the format name: 
+	 * "TEXT_LAYOUT_MARKUP". The second format is a plain-text string, which uses the standard 
+	 * Clipboard.TEXT_FORMAT name.</p>
+	 * 
+	 * <p>The methods of the TextClipboard class are static functions, you do not need to
+	 * create an instance of TextClipboard.</p>  
+	 * 
+	 * @see flash.desktop.Clipboard
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	*/
+	public class TextClipboard
+	{	
+		/** @private */
+		static tlf_internal const TEXT_LAYOUT_MARKUP:String = "TEXT_LAYOUT_MARKUP";
+		
+		/** @private */
+		static tlf_internal function getTextOnClipboardForFormat(format:String):String
+		{
+			var systemClipboard:Clipboard = Clipboard.generalClipboard;
+			return (systemClipboard.hasFormat(format)) ? String(systemClipboard.getData(format)) : null;
+		}
+		
+		/**
+		 * Gets any text on the system clipboard as a TextScrap object.
+		 *  
+		 * <p>If the "TEXT_LAYOUT_MARKUP" format is available, this method converts the formatted
+		 * string into a TextScrap and returns it. Otherwise, if the Clipboard.TEXT_Format is available,
+		 * this method converts the plain-text string into a TextScrap. If neither clipboard format
+		 * is available, this method returns <code>null</code>.</p>
+		 * 
+		 * <p>Flash Player requires that the <code>getContents()</code> method be called in a paste event handler. In AIR, 
+		 * this restriction only applies to content outside of the application security sandbox.</p>
+		 * 
+		 * @see flash.events.Event#PASTE
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */										
+		public static function getContents():TextScrap
+		{
+			var retTextScrap:TextScrap = null;
+			var textFlow:TextFlow;
+			var textOnClipboard:String;
+			
+			// first look for text_layout_markup
+			textOnClipboard = getTextOnClipboardForFormat(TEXT_LAYOUT_MARKUP);
+			
+			if ((textOnClipboard != null) && (textOnClipboard != ""))
+			{
+				var originalSettings:Object = XML.settings();
+				try {
+					XML.ignoreProcessingInstructions = false;
+					XML.ignoreWhitespace = false;
+					var xmlTree:XML = new XML(textOnClipboard);
+					var beginArrayChild:XML = xmlTree..*::BeginMissingElements[0];
+					var endArrayChild:XML = xmlTree..*::EndMissingElements[0];
+					var textLayoutMarkup:XML = xmlTree..*::TextFlow[0];
+					
+					textFlow = TextConverter.importToFlow(textLayoutMarkup, TextConverter.TEXT_LAYOUT_FORMAT);
+					
+					if (textFlow != null)
+					{
+						retTextScrap = new TextScrap(textFlow);
+						retTextScrap.beginMissingArray = getBeginArray(beginArrayChild, textFlow);
+						retTextScrap.endMissingArray = getEndArray(endArrayChild, textFlow);
+					}
+				}
+				finally
+				{
+					XML.setSettings(originalSettings);
+				}			
+			}
+			
+			// if there is no retTextScrap let's get the text_format and try that
+			if (retTextScrap == null)
+			{
+				textOnClipboard = getTextOnClipboardForFormat(ClipboardFormats.TEXT_FORMAT);
+
+				if (textOnClipboard != null && textOnClipboard != "")
+				{
+					textFlow = TextConverter.importToFlow(textOnClipboard, TextConverter.PLAIN_TEXT_FORMAT);
+					if (textFlow)
+					{
+						retTextScrap = new TextScrap(textFlow);
+						var firstLeaf:FlowLeafElement = textFlow.getFirstLeaf();
+						if (firstLeaf)
+						{
+							retTextScrap.beginMissingArray.push(firstLeaf);
+							retTextScrap.beginMissingArray.push(firstLeaf.parent);
+							retTextScrap.beginMissingArray.push(textFlow);
+							
+							var lastLeaf:FlowLeafElement = textFlow.getLastLeaf();
+							retTextScrap.endMissingArray.push(lastLeaf);
+							retTextScrap.endMissingArray.push(lastLeaf.parent);
+							retTextScrap.endMissingArray.push(textFlow);
+						}
+					}
+				}
+			}
+			return retTextScrap;
+		}
+		
+		/** @private */
+		tlf_internal static function createTextFlowExportString(scrap:TextScrap):String
+		{
+			var textFlowExportString:String = "";
+			var originalSettings:Object = XML.settings();
+			try
+			{
+				XML.ignoreProcessingInstructions = false;		
+				XML.ignoreWhitespace = false;
+				XML.prettyPrinting = false;
+					
+				var exporter:ITextExporter = TextConverter.getExporter(TextConverter.TEXT_LAYOUT_FORMAT);
+				var result:String = '<?xml version="1.0" encoding="utf-8"?>\n';
+				result += "<TextScrap>\n";
+				result += getPartialElementString(scrap);
+				
+				var xmlExport:XML = exporter.export(scrap.textFlow, ConversionType.XML_TYPE) as XML;
+				result += xmlExport;
+				result += "</TextScrap>\n";				
+				textFlowExportString = result.toString();
+				XML.setSettings(originalSettings);
+			}				
+			catch(e:Error)
+			{
+				XML.setSettings(originalSettings);
+			}
+			return textFlowExportString;
+		}
+		
+		/** @private */
+		tlf_internal static function createPlainTextExportString(scrap:TextScrap):String
+		{
+			// At some point, import/export filters will be installable. We want our clipboard fomat to be
+			// predictable, so we explicitly use the PlainTextExporter 
+			// var plainTextExporter:ITextExporter = TextConverter.getExporter(TextConverter.PLAIN_TEXT_FORMAT);
+			var plainTextExporter:PlainTextExporter = new PlainTextExporter();
+			var plainTextExportString:String = plainTextExporter.export(scrap.textFlow, ConversionType.STRING_TYPE) as String;
+			
+			// The plain text exporter does not append the paragraph separator after the last paragraph
+			// When putting text on the clipboard, the last paragraph should get a separator if it was 
+			// copied through its end, i.e., if its end is not missing 
+			var lastPara:ParagraphElement = scrap.textFlow.getLastLeaf().getParagraph();
+			if (!scrap.isEndMissing(lastPara))
+				plainTextExportString += plainTextExporter.paragraphSeparator;
+			return plainTextExportString;
+		}
+		
+		/** @private */
+		tlf_internal static function setClipboardContents(textFlowExportString:String,plainTextExportString:String):void
+		{	
+			var systemClipboard:Clipboard = Clipboard.generalClipboard;
+			systemClipboard.clear();
+			systemClipboard.setData(TEXT_LAYOUT_MARKUP, textFlowExportString);
+			systemClipboard.setData(ClipboardFormats.TEXT_FORMAT, plainTextExportString);
+		}
+		/**
+		 * Puts a TextScrap onto the system clipboard.  
+		 * 
+		 * <p>The TextScrap is placed onto the system clipboard as both a Text Layout Markup
+		 * representation and a plain text representation.</p>
+		 * 
+		 * <p>Flash Player requires a user event (such as a key press or mouse click) before 
+		 * calling <code>setContents()</code>. In AIR, this restriction only applies to content outside of 
+		 * the application security sandbox. </p>
+		 * 
+		 * @param scrap The TextScrap to paste into the clipboard.
+		 * 
+		 * @see flash.events.Event#COPY
+		 * @see flash.events.Event#CUT
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+ 		 */										
+		public static function setContents(scrap:TextScrap):void
+		{
+			if (scrap == null) 
+				return;
+			var textFlowExportString:String = createTextFlowExportString(scrap);
+			var plainTextExportString:String = createPlainTextExportString(scrap);
+			setClipboardContents(textFlowExportString,plainTextExportString);
+		}
+		
+		private static function getPartialElementString(scrap:TextScrap):String
+		{
+			var beginMissingArray:Array = scrap.beginMissingArray;
+			var endMissingArray:Array = scrap.endMissingArray;
+			var beginMissingString:String = "";
+			var endMissingString:String = "";
+			var resultString:String = "";
+			
+			var curPos:int = beginMissingArray.length - 2;
+			var curFlElement:FlowElement;
+			var curFlElementIndex:int;
+			
+			if (beginMissingArray.length > 0)
+			{
+				beginMissingString = "0";
+				while (curPos >= 0)
+				{
+					curFlElement = beginMissingArray[curPos];
+					curFlElementIndex = curFlElement.parent.getChildIndex(curFlElement);
+					beginMissingString = beginMissingString + "," + curFlElementIndex;
+					curPos--;
+				}
+			}
+			
+			curPos = endMissingArray.length - 2;
+			if (endMissingArray.length > 0)
+			{
+				endMissingString = "0";
+				
+				while (curPos >= 0)
+				{
+					curFlElement = endMissingArray[curPos];
+					curFlElementIndex = curFlElement.parent.getChildIndex(curFlElement);
+					endMissingString = endMissingString + "," + curFlElementIndex;
+					curPos--;					
+				}
+			}
+			
+			if (beginMissingString != "")
+			{
+				resultString = '<BeginMissingElements value="';
+				resultString += beginMissingString;
+				resultString += '"';
+				resultString += '/>\n';
+			}
+			
+			if (endMissingString != "")
+			{
+				resultString += '<EndMissingElements value="';
+				resultString += endMissingString;
+				resultString += '"';
+				resultString += '/>\n';				
+			}
+			return resultString;
+		}
+		
+		private static function getBeginArray(beginArrayChild:XML, textFlow:TextFlow):Array
+		{
+			var beginArray:Array = new Array();
+			var curFlElement:FlowElement = textFlow;
+			if (beginArrayChild != null)
+			{
+				var value:String = (beginArrayChild.@value != undefined) ? String(beginArrayChild.@value) : "";
+				beginArray.push(textFlow);
+				var posOfComma:int = value.indexOf(",");
+				var startPos:int;
+				var endPos:int;
+				var curStr:String;
+				var indexIntoFlowElement:int;
+				while (posOfComma >= 0)
+				{
+					startPos = posOfComma + 1;
+					posOfComma = value.indexOf(",", startPos);
+					if (posOfComma >= 0)
+					{
+						endPos = posOfComma;
+					} else {
+						endPos = value.length;
+					}
+					curStr = value.substring(startPos, endPos);
+					if (curStr.length > 0)
+					{
+						indexIntoFlowElement = parseInt(curStr);
+						if (curFlElement is FlowGroupElement)
+						{
+							curFlElement = (curFlElement as FlowGroupElement).getChildAt(indexIntoFlowElement);
+							beginArray.push(curFlElement);
+						}
+					}
+				}				
+			}
+			return beginArray.reverse();
+		}
+		
+		private static function getEndArray(endArrayChild:XML, textFlow:TextFlow):Array
+		{
+			var endArray:Array = new Array();
+			var curFlElement:FlowElement = textFlow;
+			if (endArrayChild != null)
+			{
+				var value:String = (endArrayChild.@value != undefined) ? String(endArrayChild.@value) : "";
+				endArray.push(textFlow);
+				var posOfComma:int = value.indexOf(",");
+				var startPos:int;
+				var endPos:int;
+				var curStr:String;
+				var indexIntoFlowElement:int;
+				while (posOfComma >= 0)
+				{
+					startPos = posOfComma + 1;
+					posOfComma = value.indexOf(",", startPos);
+					if (posOfComma >= 0)
+					{
+						endPos = posOfComma;
+					} else {
+						endPos = value.length;
+					}
+					curStr = value.substring(startPos, endPos);
+					if (curStr.length > 0)
+					{
+						indexIntoFlowElement = parseInt(curStr);
+						if (curFlElement is FlowGroupElement)
+						{
+							curFlElement = (curFlElement as FlowGroupElement).getChildAt(indexIntoFlowElement);
+							endArray.push(curFlElement);
+						}
+					}
+				}				
+			}
+			return endArray.reverse();
+		}
+
+		
+	} // end TextClipboard class
+}
+
+class TextClipboardSingletonEnforcer {}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/TextFlowEdit.as b/textLayout_edit/src/flashx/textLayout/edit/TextFlowEdit.as
new file mode 100755
index 0000000..aedb08f
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/TextFlowEdit.as
@@ -0,0 +1,1245 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.DivElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	[ExcludeClass]
+	/**
+	 * Encapsulates all methods necessary for dynamic editing of a text.  The methods are all static member functions of this class.
+     * @private - because we can't make it tlf_internal. Used by the operations package 
+	 */	
+	public class TextFlowEdit
+	{
+		private static function deleteRange(theFlow:FlowGroupElement, startPos:int, endPos:int):int
+		{
+			var curFlowElementIdx:int = 0;
+			var curFlowElement:FlowElement;
+			var needToMergeWhenDone:Boolean = false;
+			var relStart:int = 0;
+			var relEnd:int = 0;
+			var s:SpanElement;
+			var processedAnElement:Boolean = false;
+			var totalItemsDeleted:int = 0;
+			var curNumDeleted:int = 0;
+			var tempFlowElement:FlowElement;
+			var numItems:int;
+			
+			while (curFlowElementIdx < theFlow.numChildren)
+			{
+				curFlowElement = theFlow.getChildAt(curFlowElementIdx);
+				relStart = startPos - curFlowElement.parentRelativeStart;
+				if (relStart < 0) relStart = 0;
+				relEnd = endPos - curFlowElement.parentRelativeStart;
+							
+				if ((relStart < curFlowElement.textLength) && (relEnd > 0))
+				{
+					//at least partially selected
+					if ((relStart <= 0) && ((relEnd > curFlowElement.textLength) || ((relEnd >= curFlowElement.textLength) && (curFlowElement is ParagraphElement))))
+					{
+						//completely selected
+						// If the last character of a paragraph is part of the span, it won't get deleted. We will skip over it for now, and may delete it later as 
+						// part of a paragraph merge.
+						curNumDeleted = curFlowElement.textLength;
+						var skippingTerminator:Boolean = curFlowElementIdx == theFlow.numChildren - 1 && (curFlowElement is SpanElement) && (theFlow is ParagraphElement);
+						theFlow.replaceChildren(curFlowElementIdx, curFlowElementIdx + 1, null);
+						if (skippingTerminator)
+							++curFlowElementIdx;
+						totalItemsDeleted += curNumDeleted;
+						endPos -= curNumDeleted;
+					} else { //not completely selected
+						if (curFlowElement is SpanElement) {
+							s = curFlowElement as SpanElement;
+							
+							if(relEnd > s.textLength) 
+								relEnd = s.textLength;	
+								
+							s.replaceText(relStart, relEnd, "");
+							curNumDeleted = (relEnd - relStart);
+							totalItemsDeleted += curNumDeleted;
+							endPos -= curNumDeleted;
+						} else if (!(curFlowElement is FlowGroupElement))
+						{
+							curNumDeleted = curFlowElement.textLength;
+							totalItemsDeleted += curFlowElement.textLength;
+							endPos -= curNumDeleted;
+							theFlow.replaceChildren(curFlowElementIdx, curFlowElementIdx + 1, null);			
+						} else { //it must be a FlowGroupElement of some kind
+							if ((!processedAnElement) && (relEnd >= curFlowElement.textLength))
+							{
+								if (curFlowElement is ParagraphElement)
+									needToMergeWhenDone = true;
+								else if (curFlowElement is FlowGroupElement)
+								{
+									numItems = (curFlowElement as FlowGroupElement).numChildren;
+									if (numItems > 0)
+									{
+										tempFlowElement = (curFlowElement as FlowGroupElement).getChildAt(numItems - 1);
+										if (tempFlowElement is ParagraphElement)
+										{
+											needToMergeWhenDone = true;
+										}
+									}
+								}
+							}							
+							curNumDeleted = TextFlowEdit.deleteRange(curFlowElement as FlowGroupElement, relStart, relEnd);
+							totalItemsDeleted += curNumDeleted;
+							endPos -= curNumDeleted;
+							if (needToMergeWhenDone == true) 
+								endPos++;
+							if (!(curFlowElement is ParagraphElement)) 
+								needToMergeWhenDone = false;
+						}
+						if (processedAnElement)
+						{
+							break;
+						}						
+						curFlowElementIdx++;
+					}
+					processedAnElement = true;
+				} else if (processedAnElement)
+				{
+					break;
+				} else {
+					curFlowElementIdx++;
+				}
+			}
+			if (needToMergeWhenDone)
+			{
+				joinNextParagraph(ParagraphElement(curFlowElement.getPreviousSibling()));
+			}
+			
+			return totalItemsDeleted;
+		}
+		
+		private static function isFlowElementInArray(arr:Array, fl:FlowElement):Boolean
+		{
+			if (arr != null)
+			{
+				var arrLen:int = arr.length;
+				var currPos:int = 0;
+				while (currPos < arrLen)
+				{
+					if (arr[currPos] == fl)
+					{
+						return true;
+					}
+					currPos++;
+				}
+			}
+			return false;
+		}
+				
+		private static function getContainer(flEl:FlowElement):ContainerFormattedElement
+		{
+			while (!(flEl.parent is ContainerFormattedElement))
+			{
+				flEl = flEl.parent;
+			}
+			return flEl.parent as ContainerFormattedElement;
+		}
+		
+		private static function isInsertableItem(flItem:FlowElement, missingBeginElements:Array, missingEndElements:Array):Boolean
+		{
+			return ((flItem is ParagraphElement) ||
+					(!TextFlowEdit.isFlowElementInArray(missingBeginElements, flItem) &&
+					 !TextFlowEdit.isFlowElementInArray(missingEndElements, flItem)));
+		}
+		
+		private static function putDivAtEndOfContainer(container:ContainerFormattedElement):DivElement
+		{
+			var tempDiv:DivElement = new DivElement();
+			var tempPar:ParagraphElement = new ParagraphElement();
+			tempPar.replaceChildren(0, 0, new SpanElement());
+			tempDiv.replaceChildren(0, 0, tempPar);
+			container.replaceChildren(container.numChildren, container.numChildren, tempDiv);
+			return tempDiv;			
+		}
+		
+		private static function putDivAtEndOfContainerAndInsertTextFlow(theFlow:TextFlow, pos:int, insertedTextFlow:FlowGroupElement, missingBeginElements:Array, missingEndElements:Array, separatorArray:Array):int
+		{
+			var tempFlChild:FlowElement;
+			var nextInsertionPosition:int = pos;
+			var insertContainer:ContainerFormattedElement = TextFlowEdit.getContainer(theFlow.findAbsoluteParagraph(nextInsertionPosition));						
+			var tempDiv:DivElement = TextFlowEdit.putDivAtEndOfContainer(insertContainer);
+			separatorArray.push(tempDiv);
+			while (insertedTextFlow.numChildren > 0)
+			{
+				tempFlChild = insertedTextFlow.getChildAt(0);
+				insertedTextFlow.replaceChildren(0, 1, null);
+				nextInsertionPosition = TextFlowEdit.insertTextFlow(theFlow, nextInsertionPosition, tempFlChild as FlowGroupElement, missingBeginElements, missingEndElements, separatorArray);
+			}
+			var elementIdx:int = tempDiv.parent.getChildIndex(tempDiv);
+			tempDiv.parent.replaceChildren(elementIdx, elementIdx + 1, null);
+			separatorArray.pop();
+			return nextInsertionPosition;
+		}
+		
+		private static function isContainerSeparator(fl:FlowElement, separatorArray:Array):Boolean
+		{
+			var i:int = 0;
+			var numItemsInArray:int = separatorArray.length;
+			while (i < numItemsInArray)
+			{
+				if (separatorArray[i] == fl)
+				{
+					return true;
+				}
+				i++;
+			}
+			return false;
+		}
+		
+		private static var processedFirstFlowElement:Boolean = false;
+		private static function insertTextFlow(theFlow:TextFlow, pos:int, insertedTextFlow:FlowGroupElement, missingBeginElementsInFlow:Array = null, missingEndElementsInFlow:Array = null, separatorArray:Array = null):int
+		{
+			var nextInsertionPosition:int = pos;
+						
+			if (!TextFlowEdit.isInsertableItem(insertedTextFlow, missingBeginElementsInFlow, missingEndElementsInFlow) ||
+				(insertedTextFlow is TextFlow))
+			{
+				if (insertedTextFlow is TextFlow)
+				{
+					processedFirstFlowElement = false;
+					var tempDiv:DivElement = TextFlowEdit.putDivAtEndOfContainer(theFlow as ContainerFormattedElement);
+					separatorArray = new Array();
+					separatorArray.push(tempDiv);
+				}
+				var tempFlChild:FlowElement = insertedTextFlow.getChildAt(0);
+				if (TextFlowEdit.isInsertableItem(tempFlChild, missingBeginElementsInFlow, missingEndElementsInFlow))
+				{
+					nextInsertionPosition = TextFlowEdit.putDivAtEndOfContainerAndInsertTextFlow(theFlow, nextInsertionPosition, insertedTextFlow, missingBeginElementsInFlow, missingEndElementsInFlow, separatorArray);  
+				} else {				
+					while (insertedTextFlow.numChildren > 0)
+					{
+						tempFlChild = insertedTextFlow.getChildAt(0);
+						insertedTextFlow.replaceChildren(0, 1, null);
+						nextInsertionPosition = TextFlowEdit.insertTextFlow(theFlow, nextInsertionPosition, tempFlChild as FlowGroupElement, missingBeginElementsInFlow, missingEndElementsInFlow, separatorArray);
+					}
+				}
+				
+				if (insertedTextFlow is TextFlow)
+				{
+					theFlow.replaceChildren(theFlow.numChildren - 1, theFlow.numChildren, null);
+					if (nextInsertionPosition >= theFlow.textLength)
+					{
+						nextInsertionPosition = theFlow.textLength - 1;
+					}
+					separatorArray.pop();					
+				}				
+			} else {
+				//if you are inserting at the very end of a paragraph, bump up the position
+				//by one.  Otherwise, if you are not at the end of the paragraph, split at
+				//the position, and then move up by 1.
+										
+				var leafEl:FlowLeafElement = null;
+				if (pos > 0) leafEl = theFlow.findLeaf(pos - 1);
+				var para:ParagraphElement = theFlow.findAbsoluteParagraph(pos);
+				var paraSplitIndex:int = pos - para.getAbsoluteStart();
+				var flowElIndex:int = para.parent.getChildIndex(para);
+				var okToMergeWithAfter:Boolean = true;
+				
+				if (paraSplitIndex > 0)
+				{
+					if (paraSplitIndex < (para.textLength - 1))
+					{
+						
+						para.splitAtPosition(paraSplitIndex);
+						
+					} else if ((insertedTextFlow.textLength == 1) && !processedFirstFlowElement) {
+						if (TextFlowEdit.isFlowElementInArray(missingEndElementsInFlow, insertedTextFlow) ||
+							TextFlowEdit.isFlowElementInArray(missingBeginElementsInFlow, insertedTextFlow))
+						{ 
+							processedFirstFlowElement = true;
+							return nextInsertionPosition;
+						} else {
+							
+							para.splitAtPosition(paraSplitIndex);
+									
+						}
+					} else {
+						okToMergeWithAfter = false;
+					}
+					pos++;
+				} else { //no split done. So we want to insert after the previous paragraph.
+					flowElIndex = flowElIndex - 1;
+				}
+			
+				//insert the insertedTextFlow after the paragraph at paragraphIndex
+				var paragraphContainer:FlowGroupElement = para.parent;
+				
+				if (TextFlowEdit.isContainerSeparator(paragraphContainer, separatorArray))
+				{
+					flowElIndex = paragraphContainer.parent.getChildIndex(paragraphContainer);
+					paragraphContainer = paragraphContainer.parent;
+					flowElIndex--;	
+				}
+				
+				paragraphContainer.replaceChildren(flowElIndex + 1, flowElIndex + 1, insertedTextFlow);
+				nextInsertionPosition = pos + insertedTextFlow.textLength;
+
+				if (insertedTextFlow is ParagraphElement)
+				{	
+					var missingEnd:Boolean = TextFlowEdit.isFlowElementInArray(missingEndElementsInFlow, insertedTextFlow);
+					if (okToMergeWithAfter && missingEnd)
+					{
+						// Merge the paragraph with what comes next. If the inserted paragraph is inserted to the middle or end of the paragraph,
+						// then merge the next paragraph into the inserted paragraph. If we're inserting to the start of the paragraph, merge
+						// the inserted paragraph into the next paragraph, so that the original host paragraph maintains its format settings.
+						if (paraSplitIndex == 0)
+						{
+							if (joinToNextParagraph(ParagraphElement(insertedTextFlow)))
+								nextInsertionPosition--;
+						}
+						else if (joinNextParagraph(ParagraphElement(insertedTextFlow)))
+							nextInsertionPosition--;
+					}
+
+					if (!processedFirstFlowElement)
+					{
+						if (paraSplitIndex > 0)
+						{
+							var prevSibling:ParagraphElement = insertedTextFlow.getPreviousSibling() as ParagraphElement;
+							if (prevSibling && joinNextParagraph(prevSibling))
+								nextInsertionPosition--;
+						}
+					}
+					
+					if (missingEnd)
+					{
+						var absolutePar:ParagraphElement = paragraphContainer.getTextFlow().findAbsoluteParagraph(nextInsertionPosition);
+						var absoluteParIndex:int = absolutePar.getAbsoluteStart();
+						if ((nextInsertionPosition - absolutePar.getAbsoluteStart()) == 0)
+						{
+							nextInsertionPosition--;
+						}
+					}
+				}
+				
+				
+				processedFirstFlowElement = true;			
+			}
+			return nextInsertionPosition;
+		}
+		
+		/**
+		 * Replaces the range of text positions that the <code>startPos</code> and
+		 * <code>endPos</code> parameters specify with the <code>newTextFlow</code> parameter in
+		 * <code>theFlow</code>.
+		 * <p>To delete elements, pass <code>null</code> for <code>newTextFlow</code>.</p>
+		 * <p>To insert an element, pass the same value for <code>startPos</code> and <code>endPos</code>.
+		 * <p>To insert a newline after the <code>newTextFlow</code> is inserted, pass in
+		 * <code>true</code> for <code>insertParAfter</code></p>   
+		 * <p>The new element will be inserted before the specified index.</p>
+		 * <p>To append the TextFlow, pass <code>theFlow.length</code> for <code>startPos</code> and <code>endPos</code>.</p>
+		 * 
+		 * @param theFlow The TextFlow that is being inserted into.
+		 * @param startPos The index value of the first position of the replacement range in the TextFlow.
+		 * @param endPos The index value following the end position of the replacement range in the TextFlow.
+		 * @param newTextFlow The TextFlow to be merged into theFlow.
+		 * @param missingBeginElementsInFlow Array indicating all the elements within the TextFlow that have their beginning parts chopped off.
+		 * @param missingEndElementsInFlow Array indicating all the elements within the TextFlow that have their ending parts chopped off.
+		 */				
+		public static function replaceRange(theFlow:TextFlow, startPos:int, endPos:int, textScrap:TextScrap = null):int
+		{
+			var nextInsertPosition:int = startPos;
+			if (endPos > startPos)
+			{
+				deleteRange(theFlow, startPos, endPos);
+			}
+			
+			if (textScrap != null)
+			{
+				textScrap = textScrap.clone();	// make a copy so the original isn't mutated
+				nextInsertPosition = insertTextFlow(theFlow, startPos, textScrap.textFlow, textScrap.beginMissingArray, textScrap.endMissingArray);	
+			}
+			return nextInsertPosition;
+		}
+
+		/**
+		 * Creates a copy of the TextFlow in between two positions and returns the TextFlow
+		 * within a TextScrap object.  See TextScrap for more information.
+		 * @param theFlow The TextFlow that is being copied from.
+		 * @param startPos The index value of the first position of the TextFlow being copied from.
+		 * @param endPos The index value following the end position of the TextFlow being copied from.
+		 */			 
+		public static function createTextScrap(theFlow:TextFlow, startPos:int, endPos:int):TextScrap
+		{
+			if (!theFlow || startPos >= endPos) 
+				return null;
+			var newTextFlow:TextFlow = theFlow.deepCopy(startPos, endPos) as TextFlow;
+			newTextFlow.normalize();
+			var retTextScrap:TextScrap = new TextScrap(newTextFlow);
+			if (newTextFlow.textLength > 0)
+			{
+				var fl:FlowElement = newTextFlow.getLastLeaf();
+			
+				var srcElem:FlowElement = theFlow.findLeaf(startPos);
+				var copyElem:FlowElement = newTextFlow.getFirstLeaf();
+				while (copyElem && srcElem)
+				{
+					if ((startPos - srcElem.getAbsoluteStart()) > 0)
+					{
+						retTextScrap.addToBeginMissing(copyElem);
+					}
+					copyElem = copyElem.parent;
+					srcElem = srcElem.parent;
+				}
+			
+				srcElem = theFlow.findLeaf(endPos - 1);
+				copyElem = newTextFlow.getLastLeaf();
+				if ((copyElem is SpanElement) && (!(srcElem is SpanElement)))
+				{
+					copyElem = newTextFlow.findLeaf(newTextFlow.textLength - 2);
+				}
+				
+				while (copyElem && srcElem)
+				{
+					if (endPos < (srcElem.getAbsoluteStart() + srcElem.textLength))
+					{
+						retTextScrap.addToEndMissing(copyElem);
+					}
+					copyElem = copyElem.parent;
+					srcElem = srcElem.parent;
+				}
+				return retTextScrap;
+			}
+			return null;
+		}		
+		
+		/**
+		 * Creates a TCY run out of the selected positions.
+		 * @param theFlow The TextFlow of interest.
+		 * @param startPos The index value of the first position of the TextFlow to be turned into a TCY run.
+		 * @param endPos The index value following the end position of the TextFlow to be turned into a TCY run.
+		 */	
+		public static function makeTCY(theFlow:TextFlow, startPos:int, endPos:int):Boolean
+		{
+			var madeTCY:Boolean = true;
+			var curPara:ParagraphElement = theFlow.findAbsoluteParagraph(startPos);
+			if(!curPara)
+				return false;
+			while(curPara)
+			{
+				var paraEnd:int = curPara.getAbsoluteStart() + curPara.textLength;
+				var curEndPos:int = Math.min(paraEnd, endPos);
+				
+				//we have an entire para selected and the para only contains a kParaTerminator char, which cannot be
+				//made into TCY. 
+				if(canInsertSPBlock(theFlow, startPos, curEndPos, TCYElement) && curPara.textLength > 1)
+				{
+					var new_tcyElem:TCYElement = new TCYElement();
+					
+					//don't hide an error!
+					if(madeTCY)
+						madeTCY = insertNewSPBlock(theFlow, startPos, curEndPos, new_tcyElem, TCYElement);
+					else
+						insertNewSPBlock(theFlow, startPos, curEndPos, new_tcyElem, TCYElement);
+				}
+				else
+					madeTCY = false;
+				
+				if(paraEnd < endPos)
+				{
+					curPara = theFlow.findAbsoluteParagraph(curEndPos);	
+					startPos = curEndPos;
+				}
+				else
+					curPara = null;
+			}
+			
+			return madeTCY;
+		}
+		
+		/**
+		 * Creates one or more LinkElements out of the selected positions. It will go through
+		 * every paragraph within the selected position and make links.
+		 * @param theFlow The TextFlow of interest.
+		 * @param startPos The index value of the first position of the TextFlow to be turned into a link.
+		 * @param endPos The index value following the end position of the TextFlow to be turned into a link.
+		 * @param urlString The url string to be associated with the link.
+		 */			
+		public static function makeLink(theFlow:TextFlow, startPos:int, endPos:int, urlString:String, target:String):Boolean
+		{
+			var madeLink:Boolean = true;
+			var curPara:ParagraphElement = theFlow.findAbsoluteParagraph(startPos);
+			if(!curPara)
+				return false;
+				
+			while(curPara)
+			{
+				var paraEnd:int = curPara.getAbsoluteStart() + curPara.textLength;
+				var curEndPos:int = Math.min(paraEnd, endPos);
+				var linkEndPos:int = (curEndPos == paraEnd) ? (curEndPos - 1) : curEndPos;
+				if (linkEndPos > startPos)
+				{
+					//if the end of the paragraph is < endPos, we are going across bounds
+					if(!canInsertSPBlock(theFlow, startPos, linkEndPos, LinkElement))
+					{
+						return false;
+					}
+				
+					var newLinkElement:LinkElement = new LinkElement();
+					newLinkElement.href = urlString;
+					newLinkElement.target = target;
+				
+					//don't hide an error!
+					if(madeLink)
+						madeLink = insertNewSPBlock(theFlow, startPos, linkEndPos, newLinkElement, LinkElement);
+					else
+						insertNewSPBlock(theFlow, startPos, linkEndPos, newLinkElement, LinkElement);
+				}	
+				if(paraEnd < endPos)
+				{
+					curPara = theFlow.findAbsoluteParagraph(curEndPos);	
+					startPos = curEndPos;
+				}
+				else
+					curPara = null;
+			}
+			
+			return madeLink;
+		}
+		
+		
+		/**
+		 * Removes the TCY block at the selected positions. 
+		 * @param theFlow The TextFlow of interest.
+		 * @param startPos The index value of the first position of the TextFlow.
+		 * @param endPos The index value following the end position of the TextFlow.
+		 */			
+		public static function removeTCY(theFlow:TextFlow, startPos:int, endPos:int):Boolean
+		{
+			if (endPos <= startPos)
+			{
+				return false;
+			}
+			
+			return findAndRemoveFlowGroupElement(theFlow, startPos, endPos, TCYElement);;
+		}
+		
+		/**
+		 * Removes all LinkElements under the selected positions. It will go through
+		 * every paragraph within the selected position and remove any link.
+		 * @param theFlow The TextFlow of interest.
+		 * @param startPos The index value of the first position of the TextFlow.
+		 * @param endPos The index value following the end position of the TextFlow.
+		 */			
+		public static function removeLink(theFlow:TextFlow, startPos:int, endPos:int):Boolean
+		{
+			if (endPos <= startPos)
+			{
+				return false;
+			}
+			
+			return findAndRemoveFlowGroupElement(theFlow, startPos, endPos, LinkElement);
+		}
+		
+		/**
+		 * @private
+		 * insertNewSPBlock - add a SubParagraphGroupElement (spg) to <code>theFlow</code> at the indicies specified by <code>startPos</code> and
+		 * <code>endPos</code>.  The <code>newSPB</code> will take ownership of any FlowElements within the range and will split them
+		 * as needed.  If the parent of the FlowGroupElement indicated by <code>startPos</code> is the same as <code>spgClass</code> then
+		 * the method fails and returns false because a spg cannot own children of the same class as itself.  Any spg of type <code>spgClass</code>
+		 * found within the indicies, however, is subsumed into <code>newSPB</code>, effectively replacing it.
+		 *
+		 * @param theFlow:TextFlow - The TextFlow that is the destination for the newSPB
+		 * @param startPos:int - The absolute index value of the first position of the range in the TextFlow to perform the insertion.
+		 * @param endPos:int - The index value following the end position of the range in the TextFlow to perform the insertion.
+		 * @param newSPB:SubParagraphGroupElement - The new SubParagraphElement which is to be added into theFlow.
+		 * @param spgClass:Class - the class of the fbe we intend to add.
+		 * 
+		 * Examples: Simple and complex where insertion is of <code>spgClass</code> b.  Selection is l~o
+		 *		1) <a><span>ghijklmnop</span></a>
+		 * 		2) <a><span>ghij</span><b><span>klm</span></b><span>nop</span></a>
+		 * 		3) <a><span>ghijk</span><c><span>lmn</span></c><span>op</span></a>
+		 * 
+		 */
+		tlf_internal static function insertNewSPBlock(theFlow:TextFlow, startPos:int, endPos:int, newSPB:SubParagraphGroupElement, spgClass:Class):Boolean
+		{
+			var curPos:int = startPos;
+			var curFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(curPos);
+			var elementIdx:int = 0;
+			
+			CONFIG::debug{ assert(curFBE != null, "No FBE at location curPos(" + curPos + ")!");}
+			
+			//if we are at the last "real" glyph of the paragraph, include the terminator.
+			var paraEl:ParagraphElement = curFBE.getParagraph();
+			if(endPos == (paraEl.getAbsoluteStart() + paraEl.textLength - 1))
+				++endPos;
+			
+			//before processing this any further, we need to make sure that we are not
+			//splitting a spg which is contained within the same type of spg as the curFBE's parent.
+			//for example, if we had a tcyElement inside a linkElement, then we cannot allow a link element
+			//to be made within the tcyElement as the link would not function.  As a rule, a SubParagraphElement
+			//cannot own a child of the same class.
+			//
+			//However, if the curFBE is parented by a spg and the objects have the same start and end, then we are doing
+			//a replace and we're not splitting the parent. Check if the bounds are the same and if so, don't skip it...
+			var parentStart:int = curFBE.parent.getAbsoluteStart();
+			var curFBEStart:int = curFBE.getAbsoluteStart();
+			if(curFBE.parent && curFBE.parent is spgClass && 
+				!(parentStart == curFBEStart && parentStart + curFBE.parent.textLength == curFBEStart + curFBE.textLength))
+			{
+				return false;
+			}
+			
+			//entire FBE is selected and is not a paragraph, get its parent.
+			if(!(curFBE is ParagraphElement) && curPos == curFBEStart && curPos + curFBE.textLength <= endPos)
+			{
+				elementIdx = curFBE.parent.getChildIndex(curFBE);
+				curFBE = curFBE.parent;
+			}
+			//first, if the curFBE is of the same class as the newSPB, then we need to split it to allow for insertion
+			//of the new one IF the start position is > the start of the curFBE
+			//
+			//running example after this block:
+			//	1) <a><span>ghijk</span><span>lmnop</span></a>
+			//	2) <a><span>ghij</span><b><span>k</span></b><b><span>lm</span></b><span>nop</span></a>
+			//	3) <a><span>ghijk</span><c><span>lmn</span></c><span>op</span></a> - no change
+			if(curPos >= curFBEStart)
+			{
+				if(!(curFBE is spgClass))
+					elementIdx = findAndSplitElement(curFBE, elementIdx, curPos, true);
+				else
+				{
+					elementIdx = findAndSplitElement(curFBE.parent, curFBE.parent.getChildIndex(curFBE), curPos, false);
+					curFBE = curFBE.parent;
+				}
+			}
+			
+			//now that the curFBE has been split, we want to insert the newSPB into the flow and then start absorbing the
+			//contents...
+			//running example after this block:
+			//	1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
+			//	2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
+			//	3) <a><span>ghijk</span><b></b><c><span>lmn</span></c><span>op</span></a> - no change
+			//
+		//	we need another use case here where selection is entire sbp and selection runs from the head of a spg to
+		//	part way through it - so that a) does into parent and b) goes into spg
+			
+			// if this is case 2, then the new element must go into the parent...
+			if(curFBE is spgClass)
+			{
+				curFBEStart = curFBE.getAbsoluteStart();
+				elementIdx = curFBE.parent.getChildIndex(curFBE);
+				if(curPos > curFBEStart)//we're splitting the element, not replacing it...
+					elementIdx += 1;
+				
+				//if the spg, curFBE is entirely selected then we want to use the parent, not the item itself.
+				while(endPos >= curFBEStart + curFBE.textLength)
+				{
+					//we need access to the parent, which contains both the start and end not the FBE we just split
+					curFBE = curFBE.parent;
+				}
+				curFBE.replaceChildren(elementIdx, elementIdx, newSPB);
+			}
+			else
+			{
+				//we're inserting into the curFBE
+				curFBE.replaceChildren(elementIdx, elementIdx, newSPB);
+			}
+			
+			//see subsumeElementsToSPBlock to see effects on running example
+			subsumeElementsToSPBlock(curFBE, elementIdx + 1, curPos, endPos, newSPB, spgClass);
+			
+			return true;
+		}
+		
+		
+		/**
+		 * @private
+		 * splitElement - split <code>elem</code> at the relative index of <code>splitPos</code>.  If <code>splitSubBlockContents</code>
+		 * is true, split the contents of <code>elem</code> if it is a SubParagraphGroupElement, otherwise just split <code>elem</code>
+		 * 
+		 * @param elem:FlowElement - the FlowElement to split
+		 * @param splitPos:int - The elem relative index indicating where to split
+		 * @param splitSubBlockContents:Boolean - boolean indicating whether a SubParagraphGroupElement is to be split OR that it's contents
+		 * should be split.  For example, are we splitting a link or are we splitting the child of the link
+		 * 
+		 * <spg><span>ABCDEF</span></spg>
+		 * 
+		 * if <code>splitPos</code> indicated index between C and D, then if <code>splitSubBlockContents</code> equals true,
+		 * result is:
+		 * 
+		 * <spg><span>ABC</span><span>DEF</span></spg>
+		 * 
+		 * if <code>splitSubBlockContents</code> equals false, result is:
+		 * 
+		 * <spg><span>ABC</span></spg><spg><span>DEF</span></spg>
+		 */
+		tlf_internal static function splitElement(elem:FlowElement, splitPos:int, splitSubBlockContents:Boolean):void
+		{
+			CONFIG::debug{ assert(splitPos < elem.textLength, "trying to splic FlowElement at illegal index!"); }
+			if (elem is SpanElement)
+			{
+				SpanElement(elem).splitAtPosition(splitPos);
+			}
+			else if(elem is SubParagraphGroupElement && splitSubBlockContents)
+			{
+				var subBlock:SubParagraphGroupElement = SubParagraphGroupElement(elem);
+				// Split the SpanElement of the block at splitPos.  If the item at the splitPos is not a SpanElement, no action occurs.
+				var tempElem:SpanElement = subBlock.findLeaf(splitPos) as SpanElement;
+				if (tempElem)
+					tempElem.splitAtPosition(splitPos - tempElem.getElementRelativeStart(subBlock));
+			}
+			else if (elem is FlowGroupElement)
+			{
+				FlowGroupElement(elem).splitAtPosition(splitPos);
+			}
+			else
+			{
+				CONFIG::debug { assert(false, "Trying to split on an illegal FlowElement"); }				
+			}
+		}
+		
+		/**
+		 * @private
+		 * findAndSplitElement - starting at the child <code>elementIdx</code> of <code>fbe</code>, iterate
+		 * through the elements untill we find the one located at the aboslute index of <code>startIdx</code>. Upon
+		 * locating the child, split either the element itself OR its children based on the value of <code>splitSubBlockContents</code>
+		 * 
+		 * @param fbe:FlowGroupElement - the FBE into which the newSPB is being inserted.
+		 * @param elementIdx:int - The index into the <code>fbe's</code> child list to start
+		 * @param startIdx:int - The absolute index value into the TextFlow.
+		 * @param splitSubBlockContents:Boolean - boolean indicating whether a subElement is to be split OR that it's contents
+		 * should be split.  For example, are we splitting a link or are we splitting the child of the link
+		 * 
+		 * <p>ZYX<link>ABCDEF</link>123</p>
+		 * 
+		 * if we are inserting a TCY into the link, splitSubBlockContents should be false. We want to split the span ABCDEF such that result is:
+		 * <p>ZYX<link>AB<tcy>CD</tcy>EF</link>123</p>
+		 * 
+		 * if we are creating a new link from X to B, then we want the link to split and splitSubBlockContents should be false:
+		 * 
+		 * <p>ZY<link>XAB</link><link>CDEF</link>123</p>
+		 * 
+		 * @return int - the index of the last child of <code>fbe</code> processed.
+		 */
+		tlf_internal static function findAndSplitElement(fbe:FlowGroupElement, elementIdx:int, startIdx:int, splitSubBlockContents:Boolean):int
+		{
+			var curFlowEl:FlowElement = null;
+			var curIndexInPar:int = startIdx - fbe.getAbsoluteStart();
+			
+			while(elementIdx < fbe.numChildren)
+			{
+				curFlowEl = fbe.getChildAt(elementIdx);
+				if (curIndexInPar == curFlowEl.parentRelativeStart)
+					return elementIdx;
+				if ((curIndexInPar > curFlowEl.parentRelativeStart) && (curIndexInPar < curFlowEl.parentRelativeEnd))
+				{
+					splitElement(curFlowEl, curIndexInPar - curFlowEl.parentRelativeStart, splitSubBlockContents); 
+				}
+				++elementIdx;
+			}
+			return elementIdx;
+		}
+		
+		/**
+		 * @private
+		 * subsumeElementsToSPBlock - incorporates all elements of <code>parentFBE</code> into
+		 * the <code>newSPB</code> between the <code>curPos</code> and <code>endPos</code>.  If a child of
+		 * <code>parentFBE</code> is of type <code>spgClass</code> then the child's contents are removed from the child,
+		 * added to the <code>newSPB</code>, the child is then removed from the <code>parentFBE</code>
+		 * 
+		 * @param parentFBE:FlowGroupElement - the FBE into which the newSPB is being inserted.
+		 * @param startPos:int - The index value of the first position of the replacement range in the TextFlow.
+		 * @param endPos:int - The index value following the end position of the replacement range in the TextFlow.
+		 * @param newSPB:SubParagraphGroupElement - the new SubParagraphGroupElement we intend to insert.
+		 * @param spgClass:Class - the class of the fbe we intend to insert.
+		 * 
+		 * @return int - the aboslute index in the text flow after insertion.
+		 * 
+		 *  Examples: Simple and complex where insertion is of <code>spgClass</class> b.  Selection is l~o
+		 *		1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
+		 *		2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
+		 * 
+		 * 	parentFBE = <a>
+		 *  elementIdx = 1) 2, 2) 3
+		 *  curPos = 5
+		 *  endPos = 9
+		 *  newSPB is of type <b>
+		 */
+		tlf_internal static function subsumeElementsToSPBlock(parentFBE:FlowGroupElement, elementIdx:int, curPos:int, endPos:int, newSPB:SubParagraphGroupElement, spgClass:Class):int
+		{
+			var curFlowEl:FlowElement = null;
+			
+			//if we have an invalid index, then skip out.  elementIdx will always point one
+			//element beyond the one we are inserting....
+			if(elementIdx >= parentFBE.numChildren)
+				return curPos;
+			
+			while (curPos < endPos)
+			{
+				//running example: curFlowEl is the element immediately after the inserted newSPB:
+				//	1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
+				//		points to span-lmnop
+				//	2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
+				//		points to b-lm
+				curFlowEl = parentFBE.getChildAt(elementIdx);
+				
+				//if the curFlowEl is of the Class we are adding (spgClass), and the entire thing is selected,
+				//then we are adding the entire block, but not spliting it - perform the split on the next block
+				
+				//I think this can be safely removed from here as ownership of contents is handled below.
+				//leaving in commented out code in case we need to revert - gak 05.01.08
+			/*	if(curFlowEl is spgClass && curPos == curFlowEl.getAbsoluteStart() && curFlowEl.getAbsoluteStart() + curFlowEl.textLength <= endPos)
+				{
+					curPos = parentFBE.getAbsoluteStart() + parentFBE.textLength;
+					continue;
+				}*/
+				
+				//if the endPos is less than the length of the curFlowEl, then we need to split it.
+				//if the curFlowEl is NOT of class type spgClass, then we need to break it
+				//
+				//Use case: splitting a link in two (or three as will be the result with head and tail sharing
+				//attributes...
+				//running example 1 hits this, but 2 does not. Using variation of 2:
+				//
+				// example: 1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
+				// 			2a) <a><span>fo</span><b></b><b><span>obar</span></b></a> - selection: from o~a
+				//
+				// after this code:
+				//			1) <a><span>ghijk</span><b></b><span>lmno</span><span>p</span></a>
+				//			2a) <a><span>fo</span><b></b><b><span>oba</span></b><b><span>or</span></b></a>
+				if ((curPos + curFlowEl.textLength) > endPos)
+				{
+					splitElement(curFlowEl, endPos - curFlowEl.getAbsoluteStart(), !(curFlowEl is spgClass));  //changed to curFlowEl from newSPB as newSPB should be of type spgClass
+				}
+				
+				//add the length before replacing the elements
+				curPos += curFlowEl.textLength;
+				
+				//running example: after parentFBE.replaceChildren
+				//
+				//	1) curFlowEl = <span>lmno</span>
+				//		<a><span>ghijk</span><b></b>{curFlowEl}<span>p</span></a>
+				//
+				//	2) curFlowEl = <b><span>lm</span></b>
+				//		<a><span>ghij</span><b><span>k</span></b><b></b>{curFlowEl}<span>nop</span></a>
+				parentFBE.replaceChildren(elementIdx, elementIdx + 1, null);
+				
+				//if the curFlowEl is of type spgClass, then we need to take its children and
+				//add them to the newSPB because a spg cannot contain a child of the same class
+				//as itself
+				//
+				// exmaple: 2) curFlowEl = <b><span>lm</span></b>
+				if (curFlowEl is spgClass)
+				{
+					var subBlock:SubParagraphGroupElement = curFlowEl as SubParagraphGroupElement;
+					//elementCount == 1 - <span>lm</span>
+					while (subBlock.numChildren > 0)
+					{
+						//fe[0] = <span>lm</span>
+						var fe:FlowElement = subBlock.getChildAt(0);
+						//<span></span>
+						subBlock.replaceChildren(0, 1, null);
+						//<b><span>lm</span></b>
+						newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, fe);
+					}
+					//when compelete, example 2 is:
+					//2) <a><span>ghij</span><b><span>k</span></b><b><span>lm</span></b><span>nop</span></a>
+				}
+				else 
+				{
+					//example 1, curFlowEl is <span>lmno</span>, so this is not hit
+					//
+					// extending element <a> from foo~other
+					// <a>foo</a><b>bar<a>other</a><b>
+					// curFlowEl = <b>bar<a>other</a><b>
+					//
+					// since <b> is a spg, we need to walk it's contents and remove any <a> elements
+					if(curFlowEl is SubParagraphGroupElement)
+					{
+						//we need to dive into this spgClass and remove any fbes of type spgClass
+						//pass in the curFlowEl as the newSPB, remove any spgs of type spgClass, then 
+						//perform the replace on the newSPB passed in here
+						//
+						//ignore the return value of the recursive call as the length has already been
+						//accounted for above
+						flushSPBlock(curFlowEl as SubParagraphGroupElement, spgClass);
+					}
+					newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, curFlowEl);
+					
+					if(newSPB.numChildren == 1 && curFlowEl is SubParagraphGroupElement)
+					{
+						var childSPGE:SubParagraphGroupElement = curFlowEl as SubParagraphGroupElement;
+						//running example:
+						//a.precedence = 800, tcy.precedence = kMinSPGEPrecedence
+						//this = <tcy><a><span>fooBar</span></a><tcy>
+						//childSPGE = <a><span>fooBar</span></a>
+						if(childSPGE.textLength == newSPB.textLength && (curPos >= endPos))
+						{
+							CONFIG::debug { assert(childSPGE.precedence != newSPB.precedence, "normalizeRange found two equal SPGEs"); }
+	
+							//if the child's precedence is higher than mine, I need to swap
+							if(childSPGE.precedence > newSPB.precedence)
+							{
+								//first, remove the child
+								//this = <tcy></tcy>
+								newSPB.replaceChildren(0,1,null);
+								
+								//we need to flop this object for the child
+								while(childSPGE.numChildren > 0)
+								{
+									//tempFE = <span>fooBar</span>
+									var tempFE:FlowElement = childSPGE.getChildAt(0);
+									//child = <a></a>
+									childSPGE.replaceChildren(0,1,null);
+									//this = <tcy><span>fooBar</span></tcy>
+									newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, tempFE);
+								}
+								
+								var myIdx:int = newSPB.parent.getChildIndex(newSPB);
+								CONFIG::debug{ assert(myIdx >= 0, "Invalid index!  How can a SubParagraphGroupElement normalizing not have a parent!"); }
+								
+								//add childSPGE in my place
+								newSPB.parent.replaceChildren(myIdx, myIdx + 1, childSPGE)
+								
+								//childSPGE = <tcy><a><span>fooBar</span></a></tcy>
+								childSPGE.replaceChildren(0,0,newSPB);
+							}
+						}
+					}
+				}
+				
+			}
+	
+			return curPos;
+		}
+		
+		/**
+		 * @private
+		 * findAndRemoveFlowGroupElement 
+		 *
+		 * @param theFlow The TextFlow that is containing the elements to remove.
+		 * @param startPos The index value of the first position of the range in the TextFlow where we want to perform removal.
+		 * @param endPos The index value following the end position of the range in the TextFlow where we want to perform removal.
+		 * @param fbeClass Class the class of the fbe we intend to remove.
+		 * 
+		 * Walks through the elements of <code>theFlow</code> looking for any FlowGroupElement of type <code>fbeClass</class>
+		 * On finding one, it removes the FBE's contents and adds them back into the FBE's parent.  If the class of object is
+		 * embedded within another spg and this removal would break the parent spg, then the method does nothing.
+		 * 
+		 * Example:
+		 * 	<link>ABC<tcy>DEF</tcy>GHI</link>
+		 * 	Selection is on E and removal of link is attempted.
+		 * 	Because E is a child of a spg (tcy), and removing the link from E would split the parent spg (link),
+		 *  the action is disallowed.
+		 * 
+		 * Running example:
+		 * 	1) <link><tcy><span>foo</span></tcy><span>bar</span></link>
+		 * @return Boolean - true if items are removed or none are found.  false if operation is illegal.
+		 */ 
+		tlf_internal static function findAndRemoveFlowGroupElement(theFlow:TextFlow, startPos:int, endPos:int, fbeClass:Class):Boolean
+		{
+			var curPos:int = startPos;
+			var curEl:FlowElement;
+			
+			//walk through the elements
+			while (curPos < endPos)
+			{
+				var containerFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(curPos);
+				
+				//if the start of the parent is the same as the start of the current containerFBE, then
+				//we potentially have the wrong object.  We need to walk up the parents until we get to
+				//the one which starts at our start AND is the topmost object at that index.
+				//example: <a><b>foo</b> bar</a> - getting the object at "f" will yield the <b> element, not <a>
+				while(containerFBE.parent && containerFBE.parent.getAbsoluteStart() == containerFBE.getAbsoluteStart() && 
+					!(containerFBE.parent is ParagraphElement)) //don't go beyond paragraph
+				{
+					containerFBE = containerFBE.parent;
+				}
+				
+				//if the absoluteFBE is the item we are trying to remove, we need to work with its parent, so
+				//reassign containerFBE.  For example, if an entire link were selected, we'd need to get it's parent to
+				//perform the removal
+				if(containerFBE is fbeClass)
+					containerFBE = containerFBE.parent;
+					
+				//before processing this any further, we need to make sure that we are not
+				//splitting a spg which is contained within the same type of spg as the curFBE's parent.
+				//for example, if we had a tcyElement inside a linkElement, then we cannot allow a link element
+				//to be broken within the tcyElement as the link would have to split the TCY.
+				var ancestorOfFBE:FlowGroupElement = containerFBE.parent;
+				while(ancestorOfFBE != null && !(ancestorOfFBE is fbeClass))
+				{
+					if(ancestorOfFBE.parent is fbeClass)
+					{
+						return false;
+					}
+					ancestorOfFBE = ancestorOfFBE.parent;
+				}
+				
+				//if this is a sbe block contained in another sbe, and it is entire within the 
+				//selection bounds, we need to use the parent sbe's container.  If it is splitting
+				//the child sbe, we don't allow this and it is handled later...
+				var containerFBEStart:int = containerFBE.getAbsoluteStart();
+				if(ancestorOfFBE is fbeClass && (containerFBEStart >= curPos && containerFBEStart + containerFBE.textLength <= endPos))
+					containerFBE = ancestorOfFBE.parent;
+					
+				var childIdx:int = containerFBE.findChildIndexAtPosition(curPos - containerFBEStart);
+				curEl = containerFBE.getChildAt(childIdx);
+				if(curEl is fbeClass)
+				{
+					CONFIG::debug{ assert(curEl is SubParagraphGroupElement, "Wrong FBE type!  Trying to remove illeage FBE!") };
+					var curFBE:FlowGroupElement = curEl as FlowGroupElement;
+					
+					//get it's parent and the index of the curFBE
+					var parentBlock:FlowGroupElement = curFBE.parent;
+					var idxInParent:int = parentBlock.getChildIndex(curFBE);
+					
+					//if the curPos is not at the head of the SPB, then we need to split it here
+					//curFBE will point to the FBE starting at curPos
+					if(curPos > curFBE.getAbsoluteStart())
+					{
+						splitElement(curFBE, curPos - curFBE.getAbsoluteStart(), false);
+						curPos = curFBE.getAbsoluteStart() + curFBE.textLength;
+						continue;
+					}
+					
+					//if curFBE goes beyond the endPos, then we need to split off the tail.
+					if (curFBE.getAbsoluteStart() + curFBE.textLength > endPos)
+					{
+						splitElement(curFBE, endPos - curFBE.getAbsoluteStart(), false);
+					}
+				
+					//apply the length of the curFBE to the curPos tracker.  Do this before 
+					//removing the contents or it will be 0!
+					curPos = curFBE.getAbsoluteStart() + curFBE.textLength;
+					
+					//walk all the contents of the FBE into it's parent container
+					while (curFBE.numChildren > 0)
+					{
+						var childFE:FlowElement = curFBE.getChildAt(0);
+						curFBE.replaceChildren(0, 1, null);
+						parentBlock.replaceChildren(idxInParent, idxInParent, childFE);
+						idxInParent++; 
+					}
+					
+					//remove the curFBE
+					parentBlock.replaceChildren(idxInParent, idxInParent + 1, null);
+				}
+				else if(curEl is SubParagraphGroupElement) //check all the parents...
+				{
+					var curSPB:SubParagraphGroupElement = SubParagraphGroupElement(curEl);
+					if(curSPB.numChildren == 1)
+						curPos = curSPB.getAbsoluteStart() + curSPB.textLength;
+					else
+					{
+						curEl = curSPB.getChildAt(curSPB.findChildIndexAtPosition(curPos - curSPB.getAbsoluteStart()));
+						curPos = curEl.getAbsoluteStart() + curEl.textLength;
+					}
+				}
+				else
+				{
+					//the current block isn't the type we're looking for, so just go to the end of the
+					//FlowElement and continue
+					curPos = curEl.getAbsoluteStart() + curEl.textLength;
+				}
+				
+			}
+			
+			return true;
+		}
+		
+		/**
+		 * @private
+		 * canInsertSPBlock 
+		 * 
+		 * validate that we a valid selection to allow for insertion of a subBlock.  The rules are as
+		 * follows:
+		 * 	endPos > start
+		 * 	the new block will not span multiple paragraphs
+		 *  if the block is going into a SubParagraphGroupElement, it must not split the block:
+		 * 		example:  Text 		- ABCDEFG with a link on CDE
+		 * 		legal new Block		- D, CD, CDE, [n-chars]CDE[n1-chars]
+		 * 		illegal new Block 	- [1 + n-chars]C[D], [D]E[1 + n-chars]
+		 * 			exception - if the newBlock is the same class as the one we are trying to split
+		 * 			then we can truncate the original and add its contents to the new one, or extend it
+		 * 			as appropriate
+		 * 
+		 * @param theFlow The TextFlow that is containing the elements to validate.
+		 * @param startPos The index value of the first position of the range in the TextFlow to test.
+		 * @param endPos The index value following the end position of the range in the TextFlow to test.
+		 * @param blockClass Class the class of the fbe we intend to insert.
+		 */
+		tlf_internal static function canInsertSPBlock(theFlow:TextFlow, startPos:int, endPos:int, blockClass:Class):Boolean
+		{
+			if(endPos <= startPos)
+				return false;
+				
+			var anchorFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(startPos);
+			if(anchorFBE.getParentByType(blockClass))
+				anchorFBE = anchorFBE.getParentByType(blockClass) as FlowGroupElement;
+				
+			var tailFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(endPos - 1);
+			if(tailFBE.getParentByType(blockClass))
+				tailFBE = tailFBE.getParentByType(blockClass) as FlowGroupElement;
+			
+			//if these are the same FBEs then we are safe to insert a SubParagraphGroupElement
+			if(anchorFBE == tailFBE)
+				return true;
+			//make sure that the two FBEs belong to the same paragraph!
+			else if(anchorFBE.getParagraph() != tailFBE.getParagraph())
+				return false;
+			else if(anchorFBE is blockClass && tailFBE is blockClass)//they're the same class, OK to merge, split, etc...
+				return true;
+			else if(anchorFBE is SubParagraphGroupElement && !(anchorFBE is blockClass))
+			{
+				var anchorStart:int = anchorFBE.getAbsoluteStart();
+				if(startPos > anchorStart && endPos > anchorStart + anchorFBE.textLength)
+					return false;
+			}
+			else if((anchorFBE.parent is SubParagraphGroupElement || tailFBE.parent is SubParagraphGroupElement)
+				&& anchorFBE.parent != tailFBE.parent)
+			{
+				//if either FBE parent is a SPGE and they are not the same, prevent the split.  
+				return false;
+			}	
+			
+			//if we got here, then the anchorFBE is OK, check the tail.  If endPos is pointing to the
+			//0th character of a FlowGroupElement, we don't need to worry about the tail.
+			if(tailFBE is SubParagraphGroupElement && !(tailFBE is blockClass) && endPos > tailFBE.getAbsoluteStart())
+			{
+				var tailStart:int = tailFBE.getAbsoluteStart();
+				if(startPos < tailStart && endPos < tailStart + tailFBE.textLength)
+					return false;
+			}	
+			return true;
+		}
+		
+		/**
+		 * @private flushSPBlock recursively walk a spg looking for elements of type spgClass.  On finding one,
+		 * remove it's children and then remove the object itself.  Since spg's cannot hold children of the same type
+		 * as themselves, recursion is only needed for spg's of a class other than that of spgClass.
+		 * 
+		 * example: subPB = <b>bar<a>other</a><b> extending an <a> element to include all of "other"
+		 */ 
+		tlf_internal static function flushSPBlock(subPB:SubParagraphGroupElement, spgClass:Class):void
+		{
+			var subParaIter:int = 0;
+	
+			//example, subPB has 2 elements, <span>bar</span> and <a><span>other</span></a>
+			while(subParaIter < subPB.numChildren)
+			{
+				//subParaIter == 0, subFE = <span>bar</span> skip the FE and move to next
+				//subParaIter == 1, subFE = <a><span>other</span></a> - is a spgClass
+				var subFE:FlowElement = subPB.getChildAt(subParaIter);
+				if(subFE is spgClass)
+				{
+					//subParaIter == 1, subFE = <a><span>other</span></a>
+					var subChildFBE:FlowGroupElement = subFE as FlowGroupElement;
+					while(subChildFBE.numChildren > 0)
+					{
+						//subFEChild = <span>other</span>
+						var subFEChild:FlowElement = subChildFBE.getChildAt(0);
+						//subFEChild = <a></a>
+						subChildFBE.replaceChildren(0, 1, null);
+						//subPB = <b>barother<a></a><b>
+						subPB.replaceChildren(subParaIter, subParaIter, subFEChild);
+					}
+					
+					//increment so that subParaIter points to the element we just emptied
+					++subParaIter;
+					//remove the empty child
+					//subPB = <b>barother<b>
+					subPB.replaceChildren(subParaIter, subParaIter + 1, null);
+				}
+				else if(subFE is SubParagraphGroupElement)
+				{
+					flushSPBlock(subFE as SubParagraphGroupElement, spgClass);
+					++subParaIter;
+				}
+				else
+					++subParaIter;//go to next child
+			}
+		}
+		/** Joins this paragraph's next sibling to this if it is a paragraph */
+		static public function joinNextParagraph(para:ParagraphElement):Boolean
+		{		
+			if (para && para.parent)
+			{
+				var myidx:int = para.parent.getChildIndex(para);
+				if (myidx != para.parent.numChildren-1)
+				{
+					// right now, you can only merge with other paragraphs
+					var sibParagraph:ParagraphElement = para.parent.getChildAt(myidx+1) as ParagraphElement;
+					if (sibParagraph)
+					{						
+						while (sibParagraph.numChildren > 0)
+						{
+							var curFlowElement:FlowElement = sibParagraph.getChildAt(0);
+							sibParagraph.replaceChildren(0, 1, null);
+							para.replaceChildren(para.numChildren, para.numChildren, curFlowElement);
+						}
+						para.parent.replaceChildren(myidx+1, myidx+2, null);
+						return true;
+					}
+				}
+			} 
+			return false;
+		}
+
+		/** Joins this paragraph's next sibling to this if it is a paragraph */
+		static public function joinToNextParagraph(para:ParagraphElement):Boolean
+		{		
+			if (para && para.parent)
+			{
+				var myidx:int = para.parent.getChildIndex(para);
+				if (myidx != para.parent.numChildren-1)
+				{
+					// right now, you can only merge with other paragraphs
+					var sibParagraph:ParagraphElement = para.parent.getChildAt(myidx+1) as ParagraphElement;
+					if (sibParagraph)
+					{			
+						// Add the first paragraph's children to the front of the next paragraph's child list
+						var addAtIndex:int = 0;
+						while (para.numChildren > 0)
+						{
+							var curFlowElement:FlowElement = para.getChildAt(0);
+							para.replaceChildren(0, 1, null);
+							sibParagraph.replaceChildren(addAtIndex, addAtIndex, curFlowElement);
+							++addAtIndex;
+						}
+						para.parent.replaceChildren(myidx, myidx+1, null);
+						return true;
+					}
+				}
+			} 
+			return false;
+		}
+
+								
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/edit/TextScrap.as b/textLayout_edit/src/flashx/textLayout/edit/TextScrap.as
new file mode 100755
index 0000000..8d7bdf5
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/edit/TextScrap.as
@@ -0,0 +1,261 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.edit
+{
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	/**
+	 * The TextScrap class represents a fragment of a text flow.
+	 * 
+	 * <p>A TextScrap is a holding place for all or part of a TextFlow. A range of text can be copied 
+	 * from a TextFlow into a TextScrap, and pasted from the TextScrap into another TextFlow.</p>
+	 *
+	 * @see flashx.textLayout.elements.TextFlow
+	 * @see flashx.textLayout.edit.SelectionManager
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	*/	
+	public class TextScrap
+	{	
+		private var _textFlow:TextFlow;
+		private var _beginMissingArray:Array;
+		private var _endMissingArray:Array;
+
+		/**
+		 * Creates a TextScrap object.
+		 * 
+		 * <p>Use the <code>createTextScrap()</code> method to create a TextScrap object from
+		 * a range of text represented by a TextRange object.</p>
+		 *  
+		 * @param textFlow if set, the new TextScrap object contains the entire text flow.
+		 * Otherwise, the TextScrap object is empty.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */												
+		public function TextScrap(textFlow:TextFlow = null)
+		{
+			_textFlow = textFlow;
+			_textFlow.flowComposer = null;	// no flowcomposer in a TextScrap
+			_beginMissingArray = new Array();
+			_endMissingArray = new Array();
+		}
+
+		/**
+		 * Creates a TextScrap object from a range of text represented by a TextRange object.
+		 * 
+		 * @param range the TextRange object representing the range of text to copy.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public static function createTextScrap(range:TextRange):TextScrap
+		{
+			return TextFlowEdit.createTextScrap(range.textFlow, range.absoluteStart, range.absoluteEnd);
+		}
+		
+		/** @private
+		 * Gets the TextFlow that is currently in the TextScrap.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */												
+		tlf_internal function get textFlow():TextFlow
+		{
+			return _textFlow;
+		}
+		
+		/**
+		 * @private
+		 * 
+		 * Indicates whether the specified FlowElement has it's beginning part missing.
+		 */												
+		tlf_internal function isBeginMissing(fl:FlowElement):Boolean
+		{
+			var arrLen:int = _beginMissingArray.length;
+			var currPos:int = 0;
+			while (currPos < arrLen)
+			{
+				if (_beginMissingArray[currPos] == fl)
+				{
+					return true;
+				}
+				currPos++;
+			}
+			return false;
+		}
+		
+		/**
+		 * @private
+		 * 
+		 * Indicates whether the specified FlowElement has it's end part missing.
+		 */												
+		tlf_internal function isEndMissing(fl:FlowElement):Boolean
+		{
+			var arrLen:int = _endMissingArray.length;
+			var currPos:int = 0;
+			while (currPos < arrLen)
+			{
+				if (_endMissingArray[currPos] == fl)
+				{
+					return true;
+				}
+				currPos++;
+			}
+			return false;			
+		}
+
+		/**
+		 * @private
+		 * 
+		 * Indicates that the specified FlowElement has it's beginning part missing.
+		 */														
+		tlf_internal function addToBeginMissing(fl:FlowElement):void
+		{
+			_beginMissingArray.push(fl);
+		}
+
+		/**
+		 * @private
+		 * 
+		 * Indicates that the specified FlowElement has it's end part missing.
+		 */																
+		tlf_internal function addToEndMissing(fl:FlowElement):void
+		{
+			_endMissingArray.push(fl);			
+		}
+
+		/**
+		 * @private
+		 * 
+		 * Returns all the FlowElements in the TextFlow that have their beginning
+		 * parts missing.
+		 */																		
+		tlf_internal function get beginMissingArray():Array
+		{
+			return _beginMissingArray;
+		}
+
+		/**
+		 * @private
+		 * 
+		 * Returns all the FlowElements in the TextFlow that have their ending
+		 * parts missing.
+		 */																				
+		tlf_internal function get endMissingArray():Array
+		{
+			return _endMissingArray;
+		}
+
+		/**
+		 * @private
+		 * 
+		 * Sets an array of FlowElements that are missing their
+		 * beginning parts in this TextFlow.
+		 */																						
+		tlf_internal function set beginMissingArray(arr:Array):void
+		{
+			_beginMissingArray = arr;
+		}	
+
+		/**
+		 * Sets an array of FlowElements that are missing their
+		 * ending parts in this TextFlow.
+		 * @private
+		 */																						
+		tlf_internal function set endMissingArray(arr:Array):void
+		{	
+			_endMissingArray = arr;
+		}
+		
+		/**
+		 * Creates a duplicate copy of this TextScrap object.
+		 * 
+		 * @return TextScrap A copy of this TextScrap.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function clone():TextScrap
+		{
+			var t:TextFlow = textFlow.deepCopy() as TextFlow;
+			var newTextScrap:TextScrap = new TextScrap(t);
+			
+			var beginMissingArray:Array = _beginMissingArray;
+			var endMissingArray:Array = _endMissingArray;
+			
+			var curPos:int = beginMissingArray.length - 2;
+			var curFlElement:FlowElement;
+			var curFlElementIndex:int;
+			var newFlowElement:FlowElement = newTextScrap.textFlow;
+			
+			if (beginMissingArray.length > 0)
+			{
+				var newBeginArray:Array = new Array();
+				newBeginArray.push(newFlowElement);
+				while (curPos >= 0)
+				{
+					curFlElement = beginMissingArray[curPos];
+					curFlElementIndex = curFlElement.parent.getChildIndex(curFlElement);
+					if (newFlowElement is FlowGroupElement)
+					{
+						newFlowElement = (newFlowElement as FlowGroupElement).getChildAt(curFlElementIndex);
+						newBeginArray.push(newFlowElement);
+					}
+					curPos--;
+				}
+				newTextScrap.beginMissingArray = newBeginArray;
+			}
+			
+			curPos = endMissingArray.length - 2;
+			newFlowElement = newTextScrap.textFlow;
+			if (endMissingArray.length > 0)
+			{
+				var newEndArray:Array = new Array();
+				newEndArray.push(newFlowElement);
+				while (curPos >= 0)
+				{
+					curFlElement = endMissingArray[curPos];
+					curFlElementIndex = curFlElement.parent.getChildIndex(curFlElement);
+					if (newFlowElement is FlowGroupElement)
+					{
+						newFlowElement = (newFlowElement as FlowGroupElement).getChildAt(curFlElementIndex);
+						newEndArray.push(newFlowElement);
+					}
+					curPos--;					
+				}
+				newTextScrap.endMissingArray = newEndArray;
+			}
+			return newTextScrap;
+		}
+
+	} // end TextScap class
+} // end package
diff --git a/textLayout_edit/src/flashx/textLayout/events/FlowOperationEvent.as b/textLayout_edit/src/flashx/textLayout/events/FlowOperationEvent.as
new file mode 100755
index 0000000..aa76b23
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/events/FlowOperationEvent.as
@@ -0,0 +1,168 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	
+	import flashx.textLayout.operations.FlowOperation; 
+	
+	/** A TextFlow instance dispatches this event just before an operation commences
+	 * and again just after an operation completes. Although the event object
+	 * dispatched in both cases is an instance of FlowOperationEvent, the events
+	 * dispatched before and after an operation differ in significant ways.
+	 *
+	 * <p>Before any operation is carried out, a TextFlow object dispatches a FlowOperationEvent
+	 * with its <code>type</code> property set to <code>FlowOperationEvent.FLOW_OPERATION_BEGIN.</code>
+	 * You can determine what type of operation is about to commence by checking
+	 * the <code>operation</code> property. Events of type FLOW_OPERATION_BEGIN are
+	 * cancellable, which means that if you decide that the operation should not proceed,
+	 * you can call <code>Event.PreventDefault()</code> to cancel the operation.
+	 * If you cancel the operation, the operation is not performed and the 
+	 * FLOW_OPERATION_END event is not dispatched. You may also choose to call back into the
+	 * EditManager to do another operation before the operation that triggered the event is done. If you do
+	 * this, the operations you initiate in your event handler will be undone as a single
+	 * operation with the operation that triggered the event.</p>
+	 *
+	 * <p>If you allow the operation to proceed, TextFlow will dispatch a FlowOperationEvent
+	 * upon completion of the operation with its <code>type</code> property set to
+	 * <code>FlowOperationEvent.FLOW_OPERATION_END</code>. This event is dispatched
+	 * before Flash Player throws any errors that may have occurred as a result of the
+	 * operation. This gives you an opportunity to process the error before Flash Player
+	 * throws the error. You can access the error through the event's <code>error</code>
+	 * property. If you choose to handle the error in your event handler, you can prevent
+	 * Flash Player from throwing the error by cancelling the FLOW_OPERATION_END event
+	 * by calling <code>Event.preventDefault()</code>. You may also choose to call back into the
+	 * EditManager to do some additional operations. If you do this, the operations that result
+	 * will be undone as a unit with the operation that triggered the event.
+	 * </p> 
+	 *
+	 * @includeExample examples\FlowOperationEvent_example.as -noswf
+	 * @see flashx.textLayout.operations.FlowOperation
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class FlowOperationEvent extends Event
+	{
+		/** 
+		 * Defines the value of the <code>type</code> property of a <code>flowOperationBegin</code> event object.
+		 * Dispatched before an operation is executed.   Cancelling this event blocks the operation. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		
+		public static const FLOW_OPERATION_BEGIN:String = "flowOperationBegin";
+		
+		/**  
+		 * Defines the value of the <code>type</code> property of a <code>flowOperationEnd</code> event object.
+		 * Dispatched after an operation completes. Any errors are stored in <code>OperationEvent.error</code>.
+	 	 * If there is an error, cancelling this event blocks the rethrow of the error.
+	 	 * Generally speaking all errors are likely to be fatal.
+	 	 * <p>Changing an operation at this time (after it has been executed) may fail.</p> 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+	 	 */
+	 	
+		public static const FLOW_OPERATION_END:String = "flowOperationEnd";
+
+		/**  
+		 * Defines the value of the <code>type</code> property of a <code>flowOperationComplete</code> event object.
+		 * Dispatched after all operations including pending and composite operations are completed, composition is finished and the display is scrolled.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		
+		public static const FLOW_OPERATION_COMPLETE:String = "flowOperationComplete";
+				
+		private var _op:FlowOperation;
+		private var _e:Error;
+		private var _level:int;
+
+		/** 
+		 * The operation that is about to begin or has just ended.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+	         * @see flashx.textLayout.operations.FlowOperation
+		 */		
+		public function get operation():FlowOperation
+		{ return _op; }	
+		public function set operation(value:FlowOperation):void
+		{ _op = value; }	
+
+		/** 
+		 * The error thrown, if any, during an operation.  
+		 * If an error occurs during an operation, a reference to the error object is attached to the 
+		 * FLOW_OPERATION_END event. This give you the opportunity to deal with the error
+		 * before Flash Player throws the error. If you cancel the event, Flash Player will not throw the error.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get error():Error
+		{ return _e; }
+		public function set error(value:Error):void
+		{ _e = value; }
+		
+		/** 
+		 * Operations may be merged into composite operations through nesting.  This flag describes the nesting level of the operation.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function get level():int
+		{ return _level; }
+		public function set level(value:int):void
+		{ _level = value; }		
+		
+		/** Creates an event object that contains information about a flow operation.
+		 * @param type			The type of the event. Event listeners can access this information through the
+		 * inherited <code>type</code> property. There are two types: 
+		 * <code>FlowOperationEvent.FLOW_OPERATION_BEGIN</code>; 
+		 * <code>FlowOperationEvent.FLOW_OPERATION_END</code>.
+		 * @param bubbles 		Indicates whether an event is a bubbling event.This event does not bubble.
+		 * @param cancelable 	Indicates whether the behavior associated with the event can be prevented.
+		 * This event can be cancelled by calling the <code>Event.preventDefault()</code> method in
+		 * your event handler function.
+		 * @param operation		The FlowOperation that is about to commence or that has just ended.
+		 * @param error			Any Error generating during the operation.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function FlowOperationEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, operation:FlowOperation = null, level:int = 0, error:Error = null)
+		{
+			_op = operation;
+			_e  = error;
+			_level = level;
+			super(type, bubbles, cancelable);
+		}
+		
+       	/** @private */
+		override public function clone():Event
+		{
+			return new FlowOperationEvent(type, bubbles, cancelable, _op, _level, _e);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/events/SelectionEvent.as b/textLayout_edit/src/flashx/textLayout/events/SelectionEvent.as
new file mode 100755
index 0000000..db0e4df
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/events/SelectionEvent.as
@@ -0,0 +1,106 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.events
+{
+	import flash.events.Event;
+	import flashx.textLayout.edit.SelectionState;
+	
+	/** 
+	 * A TextFlow instance dispatches a SelectionEvent object when
+	 * an EditManager or SelectionManager changes or selects a range of text. 
+	 * For example, this event is dispatched not only when a range of text is
+	 * selected, but also when the selection changes because the
+	 * user clicks elsewhere in the text flow. Moreover, this
+	 * event is also dispatched when an EditManager changes
+	 * the text or text formatting within a range of text.
+	 *
+	 * @includeExample examples\SelectionEvent_example.as -noswf
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class SelectionEvent extends Event
+	{
+		/** 
+		 * The SelectionEvent.SELECTION_CHANGE constant defines the value of the 
+		 * type property of the event object for a selection event. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public static const SELECTION_CHANGE:String = "selectionChange";
+		
+		private var _selectionState:SelectionState;
+		
+		/** 
+		 * Creates an event object that contains information about a flow operation.
+		 * @param type		The type of the event. Event listeners can access this information through the
+		 * inherited <code>type</code> property. There is only one type of SelectionEvent: 
+		 * <code>SelectionEvent.SELECTION_CHANGE</code>; 
+		 * @param bubbles 	Indicates whether an event is a bubbling event.This event does not bubble.
+		 * @param cancelable 	Indicates whether the behavior associated with the event can be prevented.
+		 * @param range		An object of type ElementRange that describes the range of text selected.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function SelectionEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, selectionState:SelectionState=null)
+		{
+			_selectionState = selectionState;
+			super(type, bubbles, cancelable);
+		}
+
+		/** 
+		 * An object of type SelectionState that represents the selected range associated with this SelectionEvent.
+		 * 
+		 * <p>You can use this property, along with the ElementRange class, to create an ElementRange
+		 * instance that represents the range of selected text.
+		 * You can use the following line of code to create an instance of the
+		 * ElementRange class that represents the range of selected text
+		 * (the <code>ev</code> variable represents the event object, and the conditional operator 
+		 * is used to guard against a <code>null</code> value for the <code>selectionState</code>
+		 * property):</p>
+		 * <listing>
+		 * // Find selected element range
+		 * var range:ElementRange = ev.selectionState ?  
+		 * 	ElementRange.createElementRange(ev.selectionState.textFlow,
+		 * 	ev.selectionState.absoluteStart, ev.selectionState.absoluteEnd) : null;</listing>
+		 * 
+		 * 
+		 * 
+		 * @see flashx.textLayout.edit.ElementRange
+		 * @see flashx.textLayout.edit.SelectionState
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */		
+		public function get selectionState():SelectionState
+		{ return _selectionState; }	
+		public function set selectionState(value:SelectionState):void
+		{ _selectionState = value; }	
+		
+		
+		/** @private */
+		override public function clone():Event
+		{
+			return new SelectionEvent(type, bubbles, cancelable, _selectionState);
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyElementIDOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementIDOperation.as
new file mode 100755
index 0000000..dbdd30c
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementIDOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The ChangeElementIDOperation class encapsulates an element ID change.
+	 *
+	 * @see flashx.textLayout.elements.FlowElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyElementIDOperation extends FlowElementOperation
+	{	
+		private var _origID:String;
+		private var _newID:String;
+		
+		/** 
+		 * Creates a ChangeElementIDOperation object. 
+		 * 
+		 * <p>If the <code>relativeStart</code> or <code>relativeEnd</code> parameters are set, then the existing
+		 * element is split into two elements, one using the existing ID and the other
+		 * using the new ID. If both parameters are set, then the existing element is split into three elements.
+		 * The first and last elements of the set are both assigned the original ID.</p>
+		 * 
+		 * @param operationState Specifies the selection state before the operation
+		 * @param targetElement Specifies the element to change
+		 * @param newID The ID to assign
+		 * @param relativeStart An offset from the beginning of the target element.
+		 * @param relativeEnd An offset from the end of the target element.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function ApplyElementIDOperation(operationState:SelectionState, targetElement:FlowElement, newID:String, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			_newID = newID;
+			super(operationState,targetElement,relativeStart,relativeEnd);
+		}
+		
+		/** 
+		 * The ID assigned by this operation.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get newID():String
+		{ return _newID; }
+		public function set newID(val:String):void
+		{ _newID = val; }
+
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var targetElement:FlowElement = getTargetElement();
+			_origID = targetElement.id;
+
+			adjustForDoOperation(targetElement);
+			
+			targetElement.id = _newID;
+			return true;
+		}	
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var targetElement:FlowElement = getTargetElement();
+			targetElement.id = _origID;
+			
+			adjustForUndoOperation(targetElement);
+			
+			return originalSelectionState;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.as
new file mode 100755
index 0000000..679c7cb
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementStyleNameOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The ApplyElementStyleNameOperation class encapsulates a style name change.
+	 *
+	 * @see flashx.textLayout.elements.FlowElement#styleName
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyElementStyleNameOperation extends FlowElementOperation
+	{	
+		private var _origStyleName:String;
+		private var _newStyleName:String;
+		
+		/** 
+		 * Creates a ApplyElementStyleNameOperation object. 
+		 * 
+		 * <p>If the <code>relativeStart</code> and <code>relativeEnd</code> parameters are set, then the existing
+		 * element is split into multiple elements, the selected portion using the new 
+		 * style name and the rest using the existing style name.</p>
+		 * 
+		 * @param operationState Describes the current selection.
+		 * @param targetElement Specifies the element to change.
+		 * @param newStyleName The style name to assign.
+		 * @param relativeStart An offset from the beginning of the target element.
+		 * @param relativeEnd An offset from the end of the target element.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function ApplyElementStyleNameOperation(operationState:SelectionState, targetElement:FlowElement, newStyleName:String, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			_newStyleName = newStyleName;
+			super(operationState,targetElement,relativeStart,relativeEnd);
+		}
+		
+		/** 
+		 * The style name assigned by this operation.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get newStyleName():String
+		{ return _newStyleName; }
+		public function set newStyleName(val:String):void
+		{ _newStyleName = val; }
+
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var targetElement:FlowElement = getTargetElement();
+			_origStyleName = targetElement.styleName;
+			
+			adjustForDoOperation(targetElement);
+			
+			targetElement.styleName = _newStyleName;
+			return true;
+		}	
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var targetElement:FlowElement = getTargetElement();
+			targetElement.styleName = _origStyleName;
+			
+			adjustForUndoOperation(targetElement);
+			
+			return originalSelectionState;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.as
new file mode 100755
index 0000000..afc251f
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyElementUserStyleOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The ApplyElementUserStyleOperation class encapsulates a change in a style value of an element.
+	 *
+	 * @see flashx.textLayout.elements.FlowElement#userStyles
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyElementUserStyleOperation extends FlowElementOperation
+	{	
+		private var _styleName:String;
+		
+		private var _origValue:*;
+		private var _newValue:*;
+		
+		/** 
+		 * Creates a ApplyElementUserStyleOperation object.
+		 * 
+		 * <p>If the <code>relativeStart</code> and <code>relativeEnd</code> parameters are set, then the existing
+		 * element is split into multiple elements, the selected portion using the new 
+		 * style value and the rest using the existing style value.</p>
+		 * 
+		 * @param operationState Describes the range of text to style.
+		 * @param targetElement Specifies the element to change.
+		 * @param styleName The name of the style to change.
+		 * @param value The new style value.
+		 * @param relativeStart An offset from the beginning of the target element.
+		 * @param relativeEnd An offset from the end of the target element.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function ApplyElementUserStyleOperation(operationState:SelectionState, targetElement:FlowElement, styleName:String, value:*, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			_styleName = styleName;
+			_newValue = value;
+			
+			super(operationState,targetElement,relativeStart,relativeEnd);
+		}
+		
+		/** 
+		 * The name of the style changed. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get styleName():String
+		{ return _styleName; }
+		public function set styleName(val:String):void
+		{ _styleName = val; }
+		
+		/** 
+		 * The new style value.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get newValue():*
+		{ return _newValue; }
+		public function set newValue(val:*):void
+		{ _newValue = val; }
+
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var targetElement:FlowElement = getTargetElement();
+			_origValue = targetElement.getStyle(_styleName);
+			
+			adjustForDoOperation(targetElement);
+			
+			targetElement.setStyle(_styleName,_newValue);
+			return true;
+		}	
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var targetElement:FlowElement = getTargetElement();
+			targetElement.setStyle(_styleName,_origValue);
+			
+			adjustForUndoOperation(targetElement);
+			
+			return originalSelectionState;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatOperation.as
new file mode 100755
index 0000000..9c737ae
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatOperation.as
@@ -0,0 +1,238 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.ElementRange;
+	import flashx.textLayout.edit.ParaEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.Category;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+		
+	/**
+	 * The ApplyFormatOperation class encapsulates a style change.
+	 * 
+	 * <p>An ApplyFormatOperation applies the leaf format to the text in the 
+	 * specified range (no change is made if the specified range is a single point). 
+	 * It applies the paragraph format to any paragraphs at least partially within the range 
+	 * (or a single paragraph if the range is a single point). 
+	 * And it applies the container format to any containers at least partially within the range 
+	 * (or a single container if the range is a single point).</p>
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @includeExample examples\ApplyFormatOperation_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyFormatOperation extends FlowTextOperation
+	{
+		private var applyLeafFormat:ITextLayoutFormat;
+		private var applyParagraphFormat:ITextLayoutFormat;
+		private var applyContainerFormat:ITextLayoutFormat;
+
+		// helper array of styles to revert
+		// each entry has a begIdx, endIdx, ContainerFormat
+		private var undoLeafArray:Array;	
+		private var undoParagraphArray:Array;	
+		private var undoContainerArray:Array;	
+		
+		/** 
+		 * Creates an ApplyFormatOperation object.
+		 *
+		 *  @param operationState	Defines the text range to which the format is applied.
+		 *  @param leafFormat	 The format to apply to LeafFlowElement objects in the selected range.
+		 *  @param paragraphFormat The format to apply to ParagraphElement objects in the selected range.
+		 *  @param containerFormat The format to apply to containers in the selected range.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */		
+		public function ApplyFormatOperation(operationState:SelectionState, leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat = null)
+		{
+			super(operationState);
+			this.leafFormat = leafFormat;
+			this.paragraphFormat = paragraphFormat;
+			this.containerFormat = containerFormat;
+		}
+
+		/** 
+		 * The format properties to apply to the leaf elements in the range.
+		 * 
+		 * <p>If the range of this operation is a point, or if <code>leafFormat</code> is <code>null</code>,
+		 * then no leaf element formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get leafFormat():ITextLayoutFormat
+		{
+			return applyLeafFormat;
+		}
+		public function set leafFormat(value:ITextLayoutFormat):void
+		{
+			applyLeafFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		/** 
+		 * The format properties to apply to the paragraphs in the range.
+		 * 
+		 * <p>The formats of any paragraphs at least partially within the range are updated. 
+		 * If the range of this operation is a point, then a single paragraph is updated.
+		 * If <code>paragraphFormat</code> is <code>null</code>, then no paragraph formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get paragraphFormat():ITextLayoutFormat
+		{
+			return applyParagraphFormat;
+		}
+		public function set paragraphFormat(value:ITextLayoutFormat):void
+		{
+			applyParagraphFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		/** 
+		 * The format properties to apply to the containers in the range.
+		 * 
+		 * <p>The formats of any containers at least partially within the range are updated. 
+		 * If the range of this operation is a point, then a single container is updated.
+		 * If <code>containerFormat</code> is <code>null</code>, then no container formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get containerFormat():ITextLayoutFormat
+		{
+			return applyContainerFormat;
+		}
+		public function set containerFormat(value:ITextLayoutFormat):void
+		{
+			applyContainerFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		private function doInternal():SelectionState
+		{
+			var anyNewSelectionState:SelectionState;
+			
+			// Apply character format
+			if (applyLeafFormat)
+			{
+				if (absoluteStart != absoluteEnd)
+				{
+					var range:ElementRange = ElementRange.createElementRange(textFlow, absoluteStart,absoluteEnd);
+					
+					var begSel:int = range.absoluteStart;
+					var endSel:int = range.absoluteEnd;
+					if(endSel == textFlow.textLength - 1)
+						++endSel;
+						
+				//	CONFIG::debug { if (begSel != absoluteStart || endSel != absoluteEnd) trace("found mismatch ApplyFormatOperation"); }
+					if (!undoLeafArray)
+					{
+						undoLeafArray = new Array();
+						ParaEdit.cacheStyleInformation(textFlow,begSel,endSel,undoLeafArray);
+					}
+					ParaEdit.applyTextStyleChange(textFlow,begSel,endSel,applyLeafFormat,null);
+				}
+				else if (originalSelectionState.selectionManagerOperationState && textFlow.interactionManager)
+				{
+					// on point selection remember pendling leaf formats for next char typed
+					
+					anyNewSelectionState = originalSelectionState.clone();
+					var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(anyNewSelectionState.pointFormat);
+					newFormat.apply(applyLeafFormat);
+					anyNewSelectionState.pointFormat = newFormat;
+				}
+			}
+
+			if (applyParagraphFormat)
+			{
+				if (!undoParagraphArray)
+				{
+					undoParagraphArray = new Array();
+					ParaEdit.cacheParagraphStyleInformation(textFlow,absoluteStart, absoluteEnd,undoParagraphArray);
+				}
+				ParaEdit.applyParagraphStyleChange(textFlow,absoluteStart, absoluteEnd,applyParagraphFormat,null);
+			}
+			if (applyContainerFormat)
+			{
+				if (!undoContainerArray)
+				{
+					undoContainerArray = new Array();
+					ParaEdit.cacheContainerStyleInformation(textFlow,absoluteStart,absoluteEnd,undoContainerArray);
+				}
+				ParaEdit.applyContainerStyleChange(textFlow,absoluteStart,absoluteEnd,applyContainerFormat,null);
+			}
+			return anyNewSelectionState;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{ 
+			var newSelectionState:SelectionState = doInternal();
+			if (newSelectionState && textFlow.interactionManager)
+				textFlow.interactionManager.setSelectionState(newSelectionState);
+			return true;
+		}	
+		
+		/** @private */
+		override public function redo():SelectionState
+		{
+			var newSelectionState:SelectionState = doInternal();
+			return newSelectionState? newSelectionState : originalSelectionState;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{ 
+			var obj:Object;
+			
+			// Undo character format changes
+			for each (obj in undoLeafArray)
+				ParaEdit.setTextStyleChange(textFlow,obj.begIdx,obj.endIdx,obj.style);
+
+			// Undo paragraph format changes
+			for each (obj in undoParagraphArray)
+				ParaEdit.setParagraphStyleChange(textFlow,obj.begIdx,obj.endIdx,obj.attributes);
+
+			// Undo container format changes
+			for each (obj in undoContainerArray)
+				ParaEdit.setContainerStyleChange(textFlow,obj);
+
+			return originalSelectionState;
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatToElementOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatToElementOperation.as
new file mode 100755
index 0000000..5ae25f9
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyFormatToElementOperation.as
@@ -0,0 +1,123 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.Category;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The ApplyFormatToElementOperation class encapsulates a style change to an element.
+	 *
+	 * <p>This operation applies one or more formats to a flow element.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.formats.TextLayoutFormat
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyFormatToElementOperation extends FlowElementOperation
+	{
+		private var _format:ITextLayoutFormat;
+		
+		private var undoCoreStyles:Object;
+				
+		/** 
+		* Creates an ApplyFormatToElementOperation object. 
+		* 
+		* @param operationState Specifies the text flow containing the element to which this operation is applied.
+		* @param targetElement specifies the element to which this operation is applied.
+		* @param format The formats to apply in this operation.
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0 
+		*/
+		public function ApplyFormatToElementOperation(operationState:SelectionState, targetElement:FlowElement, format:ITextLayoutFormat, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			super(operationState,targetElement,relativeStart,relativeEnd);
+				
+			// split up the properties by category
+			_format = format;
+		}
+				
+		/** 
+		 * The character formats applied in this operation.
+		 * 
+		 * <p>If <code>null</code> no character formats are changed.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get format():ITextLayoutFormat
+		{
+			return _format;
+		}
+		public function set format(value:ITextLayoutFormat):void
+		{
+			_format = value;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var targetElement:FlowElement = getTargetElement();
+			
+			adjustForDoOperation(targetElement);
+			
+			undoCoreStyles = targetElement.coreStyles;
+			
+			if (_format)
+			{
+				var newFormat:TextLayoutFormat = new TextLayoutFormat(targetElement.format);
+				newFormat.apply(_format);
+				targetElement.format = newFormat;
+			}
+			
+			return true;
+		}	
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var targetElement:FlowElement = getTargetElement();
+			
+			targetElement.setCoreStylesInternal (undoCoreStyles);
+			
+			adjustForUndoOperation(targetElement);
+			
+			return originalSelectionState;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyLinkOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyLinkOperation.as
new file mode 100755
index 0000000..8d315ea
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyLinkOperation.as
@@ -0,0 +1,187 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.LinkElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+	
+	/**
+	 * The ApplyLinkOperation class encapsulates a link creation or modification operation.
+	 *
+	 * @see flashx.textLayout.elements.LinkElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @includeExample examples\ApplyLinkOperation_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */			
+	public class ApplyLinkOperation extends FlowTextOperation
+	{
+		private var _textScrap:TextScrap;
+		private var _hrefString:String;
+		private var _target:String;
+		private var _extendToLinkBoundary:Boolean;
+
+		/** 
+		 * Creates an ApplyLinkOperation object.
+		 * 
+		 * @param operationState	The text range to which the operation is applied.
+		 * @param href The URI to be associated with the link.  If href is an empty string, 
+		 * the URI of links in the selection are removed.
+		 * @param target The target of the link.
+		 * @param extendToLinkBoundary Whether to extend the selection to include the entire 
+		 * text of any existing links overlapped by the selection, and then apply the change.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		function ApplyLinkOperation(operationState:SelectionState, href:String, target:String, extendToLinkBoundary:Boolean)
+		{
+			super(operationState);
+		
+			_hrefString = href;
+			_target = target;
+			_extendToLinkBoundary = extendToLinkBoundary;
+		}
+		
+		/** 
+		 * The URI to be associated with the link.  If href is an empty string, 
+		 * the URI of links in the selection are removed.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get href():String
+		{
+			return _hrefString;
+		}
+		public function set href(value:String):void
+		{
+			_hrefString = value;
+		}
+		
+		/**
+		 * The target of the link.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get target():String
+		{
+			return _target;
+		}
+		public function set target(value:String):void
+		{
+			_target = value;
+		}
+		
+		/**
+		 * Whether to extend the selection to include the entire 
+		 * text of any existing links overlapped by the selection, and then apply the change.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get extendToLinkBoundary():Boolean
+		{
+			return _extendToLinkBoundary;
+		}
+		public function set extendToLinkBoundary(value:Boolean):void
+		{
+			_extendToLinkBoundary = value;
+		}
+
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			if (absoluteStart == absoluteEnd)
+				return false;
+			
+			if (_extendToLinkBoundary)
+			{
+				var leaf:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+				var link:LinkElement = leaf.getParentByType(LinkElement) as LinkElement;
+				if (link)
+				{
+					absoluteStart = link.getAbsoluteStart();
+				}
+				
+				leaf = textFlow.findLeaf(absoluteEnd-1);
+				link = leaf.getParentByType(LinkElement) as LinkElement;
+				if (link)
+				{
+					absoluteEnd = link.getAbsoluteStart() + link.textLength;
+				}
+			}
+			//save it off so that we can restore the flow on undo			
+			_textScrap = TextFlowEdit.createTextScrap(textFlow, absoluteStart, absoluteEnd);
+				
+			if (_hrefString != "")
+			{
+				var madeLink:Boolean = TextFlowEdit.makeLink(textFlow, absoluteStart, absoluteEnd, _hrefString, _target);
+				if (!madeLink) return false;
+			}
+			else
+			{
+				TextFlowEdit.removeLink(textFlow, absoluteStart, absoluteEnd);				
+			} 
+			return true;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			if (absoluteStart != absoluteEnd && _textScrap != null) 
+				TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteEnd, _textScrap);
+			return originalSelectionState;				
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			if (absoluteStart != absoluteEnd)
+			{
+				if (_hrefString != "")
+				{
+					TextFlowEdit.makeLink(textFlow, absoluteStart, absoluteEnd, _hrefString, _target);
+				}
+				else
+				{
+					TextFlowEdit.removeLink(textFlow, absoluteStart, absoluteEnd);				
+				} 
+			}
+			return originalSelectionState;	
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ApplyTCYOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ApplyTCYOperation.as
new file mode 100755
index 0000000..8b482b1
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ApplyTCYOperation.as
@@ -0,0 +1,183 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.tlf_internal;
+	
+	import flashx.textLayout.debug.assert;
+	
+	use namespace tlf_internal;
+	
+	/** 
+	 * The ApplyTCYOperation class encapsulates a TCY transformation.
+	 *
+	 * @see flashx.textLayout.elements.TCYElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ApplyTCYOperation extends FlowTextOperation
+	{
+		
+		private var makeBegIdx:int;
+		private var makeEndIdx:int;
+		private var removeBegIdx:int;
+		private var removeEndIdx:int;
+		private var removeRedoBegIdx:int;
+		private var removeRedoEndIdx:int;
+		
+		private var _textScrap:TextScrap;
+		private var _tcyOn:Boolean;
+
+		/** 
+		 * Creates an ApplyTCYOperation object.
+		 * 
+		 * @param operationState Describes the range of text to which the operation is applied.
+		 * @param tcyValue Specifies whether to apply TCY (<code>true</code>), or remove TCY (<code>false</code>).
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function ApplyTCYOperation(operationState:SelectionState, tcyOn:Boolean)
+		{
+			super(operationState);
+			
+			if(tcyOn)
+			{
+				makeBegIdx = operationState.absoluteStart;
+				makeEndIdx = operationState.absoluteEnd;
+			}
+			else
+			{
+				removeBegIdx = operationState.absoluteStart;
+				removeEndIdx = operationState.absoluteEnd;
+			}
+			
+			_tcyOn = tcyOn;
+		}
+
+		/** 
+		 * Indicates whether the operation applies or removes TCY formatting.
+		 * 
+		 * <p>If <code>true</code>, then the operation transforms the range into a 
+		 * TCY element. If <code>false</code>, then the operation removes TCY formatting from
+		 * the first TCY element in the range.</p>
+		 * 
+		 * @see flashx.textLayout.elements.TCYElement
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get tcyOn():Boolean
+		{
+			return _tcyOn;
+		}
+		
+		public function set tcyOn(val:Boolean):void
+		{
+			_tcyOn = val;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			if (_tcyOn && makeEndIdx <= makeBegIdx)
+			{
+				return false;
+			}
+			else if(!_tcyOn && removeEndIdx <= removeBegIdx)
+			{
+				return false;
+			}
+			
+			if (_tcyOn)
+			{
+				//save it off so that we can restore the flow on undo - make and remove need different scraps		
+				_textScrap = TextFlowEdit.createTextScrap(textFlow, makeBegIdx, makeEndIdx);
+				TextFlowEdit.makeTCY(textFlow, makeBegIdx, makeEndIdx);
+			}
+			else
+			{
+				var leaf:FlowLeafElement = textFlow.findLeaf(removeBegIdx);
+				var tcyElem:TCYElement = leaf.getParentByType(TCYElement) as TCYElement
+				CONFIG::debug{ assert(tcyElem != null, "Trying to remove TCY from a non-TCY element!"); }
+				
+				//collect the bounds for redo of removal - redo bounds are only the selection, while do bounds are the whole
+				//tcyElement
+				removeRedoBegIdx = removeBegIdx;
+				removeRedoEndIdx = removeEndIdx;
+				
+				//now reset the beg and end idx's	
+				removeBegIdx = tcyElem.getAbsoluteStart();
+				removeEndIdx = removeBegIdx + tcyElem.textLength;
+				
+				//create the scrap of the whole TCY element
+				_textScrap = TextFlowEdit.createTextScrap(textFlow, removeBegIdx, removeEndIdx);
+			
+				//use the removeRedoBegIdx/removeRedoEndIdx
+				TextFlowEdit.removeTCY(textFlow, removeRedoBegIdx, removeRedoEndIdx);
+			} 
+			return true;				
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			if (_textScrap != null) {
+				if (_tcyOn)
+				{
+					TextFlowEdit.replaceRange(textFlow, makeBegIdx, makeEndIdx, _textScrap);
+				}
+				else
+				{
+					TextFlowEdit.replaceRange(textFlow, removeBegIdx, removeEndIdx, _textScrap);
+				}
+			}
+			return originalSelectionState;				
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			if(_textScrap != null)
+			{
+				if (_tcyOn)
+				{
+					TextFlowEdit.makeTCY(textFlow, makeBegIdx, makeEndIdx);
+				}
+				else
+				{
+					TextFlowEdit.removeTCY(textFlow, removeRedoBegIdx, removeRedoEndIdx);				
+				} 
+			}
+			return originalSelectionState;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOnElementOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOnElementOperation.as
new file mode 100755
index 0000000..98845dc
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOnElementOperation.as
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.ParagraphFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.Category;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The ClearFormatOnElementOperation class encapsulates a style change to an element.
+	 *
+	 * <p>This operation undefines one or more formats to a flow element.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.formats.TextLayoutFormat
+	 * @see flashx.textLayout.events.FlowOperationEvent
+
+	 * @see ApplyFormatToElementOperation
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ClearFormatOnElementOperation extends FlowElementOperation
+	{
+		private var _format:ITextLayoutFormat;
+		
+		private var undoCoreStyles:Object;
+				
+		/** 
+		* Creates an ClearFormatOnElementOperation object. 
+		* 
+		* @param operationState Specifies the text flow containing the element to which this operation is applied.
+		* @param targetElement specifies the element to which this operation is applied.
+		* @param format The formats to apply in this operation.
+		 * 
+		* @playerversion Flash 10
+		* @playerversion AIR 1.5
+	 	* @langversion 3.0 
+		*/
+		public function ClearFormatOnElementOperation(operationState:SelectionState, targetElement:FlowElement, format:ITextLayoutFormat, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			super(operationState,targetElement,relativeStart,relativeEnd);
+				
+			// split up the properties by category
+			_format = format;
+		}
+				
+		/** 
+		 * The character formats applied in this operation.
+		 * 
+		 * <p>If <code>null</code> no character formats are changed.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get format():ITextLayoutFormat
+		{
+			return _format;
+		}
+		public function set format(value:ITextLayoutFormat):void
+		{
+			_format = value;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var targetElement:FlowElement = getTargetElement();
+			
+			adjustForDoOperation(targetElement);
+			
+			undoCoreStyles = targetElement.coreStyles;
+			
+			if (_format)
+			{
+				var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(targetElement.format);
+				// this is fairly rare so this operation is not optimizied
+				for (var prop:String in TextLayoutFormat.description)
+				{
+					if (_format[prop] !== undefined)
+						newFormat[prop] = undefined;
+				} 
+				targetElement.format = newFormat;
+			}
+			
+			return true;
+		}	
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var targetElement:FlowElement = getTargetElement();
+			
+			targetElement.setCoreStylesInternal (undoCoreStyles);
+			
+			adjustForUndoOperation(targetElement);
+			
+			return originalSelectionState;
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOperation.as
new file mode 100755
index 0000000..36ac8a9
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ClearFormatOperation.as
@@ -0,0 +1,244 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.ElementRange;
+	import flashx.textLayout.edit.ParaEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.Category;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.property.Property;
+	import flashx.textLayout.tlf_internal;
+	use namespace tlf_internal;
+		
+	/**
+	 * The ClearFormatOperation class encapsulates a way to undefine formats.
+	 * 
+	 * <p>An UndefineFormatOperation undefines properties set in the leaf format to the text in the 
+	 * specified range (no change is made if the specified range is a single point). 
+	 * It undefines properties set in the paragraph format to any paragraphs at least partially within the range 
+	 * (or a single paragraph if the range is a single point). 
+	 * And it undefines properties set in the container format to any containers at least partially within the range 
+	 * (or a single container if the range is a single point).</p>
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @includeExample examples\ApplyFormatOperation_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ClearFormatOperation extends FlowTextOperation
+	{
+		private var applyLeafFormat:ITextLayoutFormat;
+		private var applyParagraphFormat:ITextLayoutFormat;
+		private var applyContainerFormat:ITextLayoutFormat;
+
+		// helper array of styles to revert
+		// each entry has a begIdx, endIdx, ContainerFormat
+		private var undoLeafArray:Array;	
+		private var undoParagraphArray:Array;	
+		private var undoContainerArray:Array;	
+		
+		/** 
+		 * Creates an ClearFormatOperation object.
+		 *
+		 *  @param operationState	Defines the text range to which the format is applied.
+		 *  @param leafFormat	 The format whose set values indicate properties to undefine to LeafFlowElement objects in the selected range.
+		 *  @param paragraphFormat The format whose set values indicate properties to undefine to ParagraphElement objects in the selected range.
+		 *  @param containerFormat The format whose set values indicate properties to undefine to ContainerController objects in the selected range.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */		
+		public function ClearFormatOperation(operationState:SelectionState, leafFormat:ITextLayoutFormat, paragraphFormat:ITextLayoutFormat, containerFormat:ITextLayoutFormat = null)
+		{
+			super(operationState);
+			this.leafFormat = leafFormat;
+			this.paragraphFormat = paragraphFormat;
+			this.containerFormat = containerFormat;
+		}
+
+		/** 
+		 * The format properties to undefine on the leaf elements in the range.
+		 * 
+		 * <p>If the range of this operation is a point, or if <code>leafFormat</code> is <code>null</code>,
+		 * then no leaf element formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get leafFormat():ITextLayoutFormat
+		{
+			return applyLeafFormat;
+		}
+		public function set leafFormat(value:ITextLayoutFormat):void
+		{
+			applyLeafFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		/** 
+		 * The format properties to undefine on the paragraphs in the range.
+		 * 
+		 * <p>The formats of any paragraphs at least partially within the range are updated. 
+		 * If the range of this operation is a point, then a single paragraph is updated.
+		 * If <code>paragraphFormat</code> is <code>null</code>, then no paragraph formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get paragraphFormat():ITextLayoutFormat
+		{
+			return applyParagraphFormat;
+		}
+		public function set paragraphFormat(value:ITextLayoutFormat):void
+		{
+			applyParagraphFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		/** 
+		 * The format properties to undefine on the containers in the range.
+		 * 
+		 * <p>The formats of any containers at least partially within the range are updated. 
+		 * If the range of this operation is a point, then a single container is updated.
+		 * If <code>containerFormat</code> is <code>null</code>, then no container formats are changed.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get containerFormat():ITextLayoutFormat
+		{
+			return applyContainerFormat;
+		}
+		public function set containerFormat(value:ITextLayoutFormat):void
+		{
+			applyContainerFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		private function doInternal():SelectionState
+		{
+			var anyNewSelectionState:SelectionState;
+
+			// Apply character format
+			if (applyLeafFormat)
+			{
+				if (absoluteStart != absoluteEnd)
+				{
+					var range:ElementRange = ElementRange.createElementRange(textFlow, absoluteStart,absoluteEnd);
+					
+					var begSel:int = range.absoluteStart;
+					var endSel:int = range.absoluteEnd;
+					if(endSel == textFlow.textLength - 1)
+						++endSel;
+						
+				//	CONFIG::debug { if (begSel != absoluteStart || endSel != absoluteEnd) trace("found mismatch ApplyFormatOperation"); }
+					if (!undoLeafArray)
+					{
+						undoLeafArray = new Array();
+						ParaEdit.cacheStyleInformation(textFlow,begSel,endSel,undoLeafArray);
+					}
+					ParaEdit.applyTextStyleChange(textFlow,begSel,endSel,null,applyLeafFormat);
+				}
+				else if (originalSelectionState.selectionManagerOperationState && textFlow.interactionManager)
+				{
+					// on point selection remember pendling leaf formats for next char typed
+					
+					anyNewSelectionState = originalSelectionState.clone();
+					// This is only a partial implementation - see watson bug 
+					// here if the format is pending we can clear it
+					// The bug is that we don't remember any pending clear that's not set in pointFormat on the next character typed
+					var newFormat:TextLayoutFormatValueHolder = new TextLayoutFormatValueHolder(anyNewSelectionState.pointFormat);
+					for (var prop:String in TextLayoutFormat.description)
+					{
+						if (applyLeafFormat[prop] !== undefined)
+							newFormat[prop] = undefined;
+					}
+					anyNewSelectionState.pointFormat = newFormat;
+				}				
+			}
+
+			if (applyParagraphFormat)
+			{
+				if (!undoParagraphArray)
+				{
+					undoParagraphArray = new Array();
+					ParaEdit.cacheParagraphStyleInformation(textFlow,absoluteStart, absoluteEnd,undoParagraphArray);
+				}
+				ParaEdit.applyParagraphStyleChange(textFlow,absoluteStart, absoluteEnd, null, applyParagraphFormat);
+			}
+			if (applyContainerFormat)
+			{
+				if (!undoContainerArray)
+				{
+					undoContainerArray = new Array();
+					ParaEdit.cacheContainerStyleInformation(textFlow,absoluteStart,absoluteEnd,undoContainerArray);
+				}
+				ParaEdit.applyContainerStyleChange(textFlow,absoluteStart,absoluteEnd, null, applyContainerFormat);
+			}
+			return anyNewSelectionState;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{ 
+			var newSelectionState:SelectionState = doInternal();
+			if (newSelectionState && textFlow.interactionManager)
+				textFlow.interactionManager.setSelectionState(newSelectionState);
+			return true;
+		}
+
+		override public function redo():SelectionState
+		{
+			var newSelectionState:SelectionState = doInternal();
+			return newSelectionState? newSelectionState : originalSelectionState;
+		}		
+
+		/** @private */
+		public override function undo():SelectionState
+		{ 
+			var obj:Object;
+			
+			// Undo character format changes
+			for each (obj in undoLeafArray)
+				ParaEdit.setTextStyleChange(textFlow,obj.begIdx,obj.endIdx,obj.style);
+
+			// Undo paragraph format changes
+			for each (obj in undoParagraphArray)
+				ParaEdit.setParagraphStyleChange(textFlow,obj.begIdx,obj.endIdx,obj.attributes);
+
+			// Undo container format changes
+			for each (obj in undoContainerArray)
+				ParaEdit.setContainerStyleChange(textFlow,obj);
+
+			return originalSelectionState;
+		}
+		
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/CompositeOperation.as b/textLayout_edit/src/flashx/textLayout/operations/CompositeOperation.as
new file mode 100755
index 0000000..76c575b
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/CompositeOperation.as
@@ -0,0 +1,218 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.tlf_internal;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.debug.assert;
+
+	use namespace tlf_internal;
+
+	/**
+	 * The CompositeOperation class encapsulates a group of transformations managed as a unit.
+	 *
+	 * <p>The CompositeOperation class provides a grouping mechanism for combining multiple FlowOperations 
+	 * into a single atomic operation. Grouping operations allows them to be undone and redone as a unit. 
+	 * For example, several single character inserts followed by several backspaces can be undone together as if 
+	 * they were a single operation. Grouping also provides a mechanism for representing
+	 * complex operations. For example, a replace operation that modifies more than one text ranges
+	 * can be represented and managed as a single composite operation.</p>
+	 * 
+	 * <p><b>Note:</b> It can be more efficient to merge individual atomic operations
+	 *  rather than to combine separate operations into a group. For example, several sequential
+	 *  character inserts can easily be represented as a single insert operation,
+	 *  and undoing or redoing that single operation is more efficient than
+	 *  undoing or redoing a group of insert operations.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class CompositeOperation extends FlowOperation
+	{
+		private var _operations:Array;
+		
+		/** 
+		 * Creates a CompositeOperation object.
+		 * 
+		 * @param operations The operations to group.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function CompositeOperation(operations:Array = null)
+		{
+			super(null);
+			this.operations = operations;
+		}
+
+		/** @private */
+		override public function get textFlow():TextFlow
+		{ return _operations.length > 0 ? _operations[0].textFlow : null; }
+		
+		/**
+		 * An array containing the operations grouped by this composite operation.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get operations():Array
+		{
+			return _operations;
+		}
+		public function set operations(value:Array):void
+		{
+			_operations = value ? value.slice() : [];	// make a copy
+		}
+		
+		/** 
+		 * Adds an additional operation to the end of the list. 
+		 * 
+		 * <p>The new operation must operate on the same TextFlow object as 
+		 * the other operations in the list.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function addOperation(operation:FlowOperation):void
+		{
+			// Can't handle operations from other TextFlows
+			if (_operations.length > 0 && operation.textFlow != textFlow)
+				return;
+				
+			CONFIG::debug { assert(_operations.length <= 0 || operation.beginGeneration == _operations[_operations.length - 1].endGeneration,
+				"adding non-contiguous operation to composite operation"); }
+			_operations.push(operation);
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			// execute all the operations in order
+			var success:Boolean = true;
+			for (var i:int = 0; i < _operations.length; i++)
+				success = success && FlowOperation(_operations[i]).doOperation();
+			
+			// return selectionState from last operation
+			return true;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			// undo all the operations in reverse order
+			var selState:SelectionState;
+			for (var i:int = _operations.length - 1; i >= 0; i--)
+				selState = FlowOperation(_operations[i]).undo();
+			
+			// return selectionState from last performed
+			// (i.e., the first in the set of operations)
+			return selState;
+		}
+		
+		/** @private */
+		public override function redo():SelectionState
+		{
+			// execute all the operations in order
+			var selState:SelectionState;
+			for (var i:int = 0; i < _operations.length; i++)
+				selState = FlowOperation(_operations[i]).redo();
+			
+			// return selectionState from last operation
+			return selState;
+		}		
+		
+		/** @private */
+		public override function canUndo():Boolean
+		{ 
+			// All operations within the CompositeOperation must have matching generation numbers, and be undoable
+			var undoable:Boolean = true;
+			var generation:int = beginGeneration;
+			var opCount:int = _operations.length;
+			for (var i:int = 0; i < opCount && undoable; i++)
+			{
+				var op:FlowOperation = _operations[i];
+				if (op.beginGeneration != generation || !op.canUndo())
+					undoable = false;
+				generation = op.endGeneration;
+			}
+			if (opCount > 0 && _operations[opCount - 1].endGeneration != endGeneration)
+				undoable = false;
+			
+			return undoable; 
+		}
+		
+		
+		/** @private */
+		tlf_internal override function merge(operation:FlowOperation):FlowOperation
+		{
+			if (operation is InsertTextOperation || operation is SplitParagraphOperation || operation is DeleteTextOperation)
+			{
+				if (this.endGeneration != operation.beginGeneration)
+					return null;
+				// For efficiency, try to combine the last low-level operation
+				// with the new operation. If that's not possible, we just add it 
+				// as an additional operation.
+				// Note that we are making various assumptions here about the technical
+				// feasability and appropriateness of merging the individual operations (e.g.,
+				// that the selection hasn't changed), relying on SelectionManager to
+				// guarantee that these are satisfied.
+				var mergedOp:FlowOperation;
+				var lastOp:FlowOperation = (_operations && _operations.length) ? 
+										FlowOperation(_operations[_operations.length - 1]) :
+										null;
+				if (lastOp) 
+					mergedOp = lastOp.merge(operation);
+				
+				if (mergedOp && !(mergedOp is CompositeOperation))
+					_operations[_operations.length - 1] = mergedOp;
+				else
+					_operations.push(operation);
+				return this;
+			}
+			return null;
+		}
+		
+//		/**
+//		 *  Add an additional operation to the end of this operation.
+//		 *  If the additional operation is itself a CompositeOperation, 
+//		 *  its child operations are just added to this operation's 
+//		 *  set of child operations.
+//		 * 	
+//		 * @param operation The operation to be merged.
+//		 * 
+//		 */
+//		private function mergeOperationViaConcatenation(operation:FlowOperation):void
+//		{
+//			var compositeOp:CompositeOperation = operation as CompositeOperation;
+//			if (compositeOp)
+//				operations = operations.concat(compositeOp.operations);
+//			else
+//				operations.push(operation);
+//		}
+
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/CopyOperation.as b/textLayout_edit/src/flashx/textLayout/operations/CopyOperation.as
new file mode 100755
index 0000000..f9d9fe5
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/CopyOperation.as
@@ -0,0 +1,85 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextClipboard;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	
+	/**
+	 * The CopyOperation class encapsulates a copy operation.
+	 * 
+	 * <p><b>Note:</b> The operation is responsible for copying the 
+	 * text scrap to the clipboard. Undonig a copy operation does not restore
+	 * the original clipboard state.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class CopyOperation extends FlowTextOperation
+	{		
+		/** 
+		 * Creates a CopyOperation object.
+		 * 
+		 * @param operationState The range of text to be copied.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function CopyOperation(operationState:SelectionState)
+		{
+			super(operationState);
+		}
+		
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			if (originalSelectionState.activePosition != originalSelectionState.anchorPosition)
+				TextClipboard.setContents(TextScrap.createTextScrap(originalSelectionState));		
+			return true;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{				
+			return originalSelectionState;	
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			return originalSelectionState;	
+
+		}		
+		
+		/** @private */
+		public override function canUndo():Boolean
+		{ return false; }
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/CutOperation.as b/textLayout_edit/src/flashx/textLayout/operations/CutOperation.as
new file mode 100755
index 0000000..17f8a29
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/CutOperation.as
@@ -0,0 +1,114 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	
+	/**
+	 * The CutOperation class encapsulates a cut operation.
+	 *
+	 * <p>The specified range is removed from the text flow.</p>
+	 * 
+	 * <p><b>Note:</b> The edit manager is responsible for copying the 
+	 * text scrap to the clipboard. Undoing a cut operation does not restore
+	 * the original clipboard state.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class CutOperation extends FlowTextOperation
+	{
+		private var _tScrap:TextScrap;
+		
+		/** 
+		 * Creates a CutOperation object.
+		 * 
+		 * @param operationState The range of text to be cut.
+		 * @param scrapToCut A copy of the deleted text.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		function CutOperation(operationState:SelectionState, scrapToCut:TextScrap)
+		{
+			super(operationState);
+			_tScrap = scrapToCut;
+		}
+		
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var beforeOpLen:int = textFlow.textLength;
+			TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteEnd, null);			
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -(absoluteEnd - absoluteStart));
+			if (textFlow.textLength == beforeOpLen)
+			{
+				_tScrap = null;
+			}			
+			return true;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			if (_tScrap != null) 
+			{
+				TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteStart, _tScrap);
+				if (textFlow.interactionManager)
+					textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, absoluteEnd - absoluteStart);
+			}				
+			return originalSelectionState;	
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			TextFlowEdit.replaceRange(textFlow, absoluteStart,absoluteEnd, null);												
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -(absoluteEnd - absoluteStart));
+			return new SelectionState(textFlow, absoluteStart, absoluteStart, null);
+		}
+		
+		/** 
+		 * scrapToCut the original removed text
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get scrapToCut():TextScrap
+		{ return _tScrap; }
+		public function set scrapToCut(val:TextScrap):void
+		{ _tScrap = val; }
+		
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/DeleteTextOperation.as b/textLayout_edit/src/flashx/textLayout/operations/DeleteTextOperation.as
new file mode 100755
index 0000000..ab7414e
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/DeleteTextOperation.as
@@ -0,0 +1,216 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionManager;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormatValueHolder;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+
+	/**
+	 * The DeleteTextOperation class encapsulates the deletion of a range of text.
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class DeleteTextOperation extends FlowTextOperation
+	{
+		private var _textScrap:TextScrap;
+		private var _allowMerge:Boolean;
+		private var _undoParaFormat:TextLayoutFormatValueHolder;
+		private var _undoCharacterFormat:TextLayoutFormatValueHolder;
+		private var _needsOldFormat:Boolean = false;
+		private var _pendingFormat:TextLayoutFormatValueHolder;
+		
+		private var _deleteSelectionState:SelectionState = null;
+		/** 
+		 * Creates a DeleteTextOperation operation.
+		 * 
+		 * @param operationState The original range of text.
+		 * @param deleteSelectionState The range of text to delete, if different from the range 
+		 * described by <code>operationState</code>. (Set to <code>null</code> to delete the range
+		 * described by <code>operationState</code>.)
+		 * @param allowMerge Set to <code>true</code> if this operation can be merged with the next or previous operation.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function DeleteTextOperation(operationState:SelectionState, deleteSelectionState:SelectionState = null, allowMerge:Boolean = false)
+		{
+			_deleteSelectionState = deleteSelectionState ? deleteSelectionState : operationState;				
+			
+			super(_deleteSelectionState);
+			originalSelectionState = operationState;
+			_allowMerge = allowMerge;
+		}
+		
+		/** 
+		 * Indicates whether this operation can be merged with operations executed before or after it.
+		 * 
+		 * <p>Some delete operations, for example, a sequence of backspace keystrokes, can be fruitfully 
+		 * merged into one operation so that undoing the operation reverses the entire sequence.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get allowMerge():Boolean
+		{
+			return _allowMerge;
+		}
+		public function set allowMerge(value:Boolean):void
+		{
+			_allowMerge = value;
+		}
+		
+		/** 
+		 * deleteSelectionState The range of text to delete
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get deleteSelectionState():SelectionState
+		{
+			return _deleteSelectionState;
+		}
+		public function set deleteSelectionState(value:SelectionState):void
+		{
+			_deleteSelectionState = value;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			// Nothing to delete
+			if (absoluteStart == absoluteEnd)
+				return false;
+				
+			_textScrap = TextFlowEdit.createTextScrap(textFlow, absoluteStart, absoluteEnd);
+			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+			var paraEl:ParagraphElement = leafEl.getParagraph(); 
+			var paraElAbsStart:int = paraEl.getAbsoluteStart();
+			
+			_pendingFormat = new TextLayoutFormatValueHolder(leafEl.format);
+						
+			if (_textScrap)
+			{
+				if ((_textScrap.textFlow.textLength == 1) && 
+						((absoluteEnd == (textFlow.textLength - 1)) || (absoluteEnd == (paraElAbsStart + paraEl.textLength))))
+			 	{
+					//special case. Always insert the paragraph
+					_textScrap.beginMissingArray = new Array();
+					_textScrap.endMissingArray = new Array();
+			 	}
+			 	
+			 	if (_textScrap.textFlow.textLength >= 1)
+			 	{
+					//save off the paragraph format of the next paragraph since we will need to set it back
+					//on an undo operation					
+					leafEl = textFlow.findLeaf(absoluteEnd);
+					paraEl = leafEl.getParagraph();
+					if (absoluteEnd == paraEl.getAbsoluteStart())
+					{
+						_undoParaFormat = new TextLayoutFormatValueHolder(paraEl.format);
+						_undoCharacterFormat = new TextLayoutFormatValueHolder(leafEl.format);
+						_needsOldFormat = true;
+					}
+				}
+			} 
+			
+			var beforeOpLen:int = textFlow.textLength;
+			TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteEnd, null);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -(absoluteEnd - absoluteStart));
+			
+			if (originalSelectionState.selectionManagerOperationState && textFlow.interactionManager)
+			{
+				// set pointFormat from leafFormat
+				var state:SelectionState = textFlow.interactionManager.getSelectionState();
+				if (state.anchorPosition == state.activePosition)
+				{
+					state.pointFormat = new TextLayoutFormatValueHolder(_pendingFormat);
+					textFlow.interactionManager.setSelectionState(state);
+				}
+			}
+
+			// nothing deleted???
+			if (beforeOpLen == textFlow.textLength)
+				_textScrap = null;
+			return true;	
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			if (_textScrap != null) {
+				TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteStart, _textScrap);
+				if (_needsOldFormat)
+				{
+					textFlow.normalize();
+					var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteEnd);
+					if (leafEl)
+					{
+						var paraEl:ParagraphElement = leafEl.getParagraph();
+						paraEl.format = _undoParaFormat;
+						leafEl.format = _undoCharacterFormat; 
+					}
+					
+				}
+				if (textFlow.interactionManager)
+					textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, absoluteEnd - absoluteStart);
+			}
+			return originalSelectionState;				
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteEnd, null);			
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -(absoluteEnd - absoluteStart));
+			return new SelectionState(textFlow,absoluteStart,absoluteStart,_pendingFormat);	
+		}
+
+		/** @private */
+		tlf_internal override function merge(op2:FlowOperation):FlowOperation
+		{
+			if (this.endGeneration != op2.beginGeneration)
+					return null;
+			var delOp:DeleteTextOperation = op2 as DeleteTextOperation;
+			if ((delOp == null) || !delOp.allowMerge || !_allowMerge)
+				return null;
+				
+			return new CompositeOperation([this, op2]);
+		}	
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/FlowElementOperation.as b/textLayout_edit/src/flashx/textLayout/operations/FlowElementOperation.as
new file mode 100755
index 0000000..2412048
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/FlowElementOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+	
+	/**
+	 * The FlowElementOperation class is the base class for operations that transform a FlowElement.
+	 *
+	 * @see flashx.textLayout.formats.TextLayoutFormat
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class FlowElementOperation extends FlowTextOperation
+	{	
+		private var nestLevel:int;
+		private var absStart:int;
+		private var absEnd:int;
+		
+		private var origAbsStart:int;
+		private var origAbsEnd:int;
+		
+		private var firstTime:Boolean = true;
+		private var splitAtStart:Boolean = false;
+		private var splitAtEnd:Boolean = false;
+		
+		private var _relStart:int = 0;
+		private var _relEnd:int = -1;
+		
+		/** 
+		 * Creates a FlowElementOperation object.
+		 *  
+		 * @param operationState Specifies the TextFlow object this operation acts upon.
+		 * @param targetElement Specifies the element this operation modifies.
+		 * @param relativeStart An offset from the beginning of the <code>targetElement</code>.
+		 * @param relativeEnd An offset from the end of the <code>targetElement</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function FlowElementOperation(operationState:SelectionState, targetElement:FlowElement, relativeStart:int = 0, relativeEnd:int = -1)
+		{
+			super(operationState);
+			
+			CONFIG::debug { 
+				var elem:FlowElement = this.targetElement;
+				for (var i:int = nestLevel; i > 0; i--)
+					elem = elem.parent;
+				
+				assert (elem is TextFlow, "ChangeElementIdOperation targetElement root is not a TextFlow!"); 
+				assert (elem == operationState.textFlow, "ChangeElementIdOperation element is not part of selectionState TextFlow"); 
+			}
+			
+			initialize(targetElement,relativeStart,relativeEnd);
+		}
+		
+		
+		private function initialize(targetElement:FlowElement, relativeStart:int, relativeEnd:int ):void
+		{
+			this.targetElement = targetElement;
+			this.relativeEnd = relativeEnd;
+			this.relativeStart = relativeStart;
+			
+			if (relativeEnd == -1)
+				relativeEnd = targetElement.textLength;
+				
+			CONFIG::debug { assert(relativeStart >= 0 && relativeStart <= targetElement.textLength,"ChangeElementIdOperation bad relativeStart"); } 
+			CONFIG::debug { assert(relativeEnd >= 0 && relativeEnd <= targetElement.textLength,"ChangeElementIdOperation bad relativeEnd"); } 
+			CONFIG::debug { assert(relativeStart <= relativeEnd,"ChangeElementIdOperation relativeStart not before relativeEnd"); } 
+
+			// If we're changing the format of the text right before the terminator, change the terminator to match.
+			// This will make it so that when the format change is undone, the terminator will be restored to previous state. Also
+			// prevents unnecessary split & join of spans (split for apply, joined during normalize).
+			if (targetElement is SpanElement && SpanElement(targetElement).hasParagraphTerminator && relativeEnd == targetElement.textLength - 1)
+				relativeEnd += 1;
+				
+			origAbsStart = absStart = targetElement.getAbsoluteStart() + relativeStart;
+			origAbsEnd   = absEnd   = absStart - relativeStart + relativeEnd;
+			
+		}
+		
+		/** 
+		 * Specifies the element this operation modifies.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get targetElement():FlowElement
+		{
+			var element:FlowElement = originalSelectionState.textFlow;
+			for (var i:int = nestLevel; i > 0; i--)
+			{
+				var groupElement:FlowGroupElement = element as FlowGroupElement;
+				element = groupElement.getChildAt(groupElement.findChildIndexAtPosition(absStart - element.getAbsoluteStart()));
+			}
+			return element;
+		}
+		public function set targetElement(value:FlowElement):void
+		{
+			nestLevel = 0;
+			for (var element:FlowElement = value; element.parent != null; element = element.parent)
+				++nestLevel;
+		}
+		
+	
+		/** 
+		 * An offset from the beginning of the <code>targetElement</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get relativeStart():int
+		{
+			return _relStart;
+		}
+		public function set relativeStart(value:int):void
+		{
+			_relStart = value;
+		}
+		
+		/** 
+		 * An offset from the start of the <code>targetElement</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get relativeEnd():int
+		{
+			return _relEnd;
+		}
+		public function set relativeEnd(value:int):void
+		{
+			_relEnd = value;
+		}
+		
+		
+		/** @private */
+		protected function getTargetElement():FlowElement
+		{
+			var element:FlowElement = this.targetElement;
+			
+			var elemStart:int = element.getAbsoluteStart();
+			var splitElement:FlowElement;	// scratch
+			// split at the back and then split at the start - that way paragraph terminators don't get in the way
+			if (absEnd != elemStart + element.textLength)
+			{
+				splitElement = element.splitAtPosition(absEnd - elemStart);
+				if (firstTime && splitElement != element)
+					splitAtEnd = true;
+			}
+				
+			if (absStart != elemStart)
+			{
+				splitElement = element.splitAtPosition(absStart-elemStart);
+				if (splitElement != element)
+				{
+					if (firstTime)
+						splitAtStart = true;
+					element = splitElement;
+				}
+			}
+			
+			firstTime = false;	
+			return element;
+		}
+		
+		
+		/** @private */
+		protected function adjustForDoOperation(targetElement:FlowElement):void
+		{
+			// adjust for undo
+			absStart = targetElement.getAbsoluteStart();
+			absEnd   = absStart + targetElement.textLength;
+		}	
+		
+		/** @private */
+		protected function adjustForUndoOperation(targetElement:FlowElement):void
+		{
+			// need to do manual merging
+			if ((splitAtEnd || splitAtStart) && (targetElement is FlowGroupElement))
+			{
+				var targetIdx:int = targetElement.parent.getChildIndex(targetElement);
+				var workElem:FlowGroupElement;
+				var child:FlowElement;
+				
+				if (splitAtEnd)
+				{
+					// merge next to targetElement
+					workElem = targetElement.parent.getChildAt(targetIdx+1) as FlowGroupElement;
+					while (workElem.numChildren)
+					{
+						child = workElem.getChildAt(0);
+						workElem.removeChildAt(0);
+						FlowGroupElement(targetElement).addChild(child);
+					}
+					targetElement.parent.removeChildAt(targetIdx+1);
+				}
+				if (splitAtStart)
+				{
+					// merge targetElement to prevElement
+					workElem = targetElement.parent.getChildAt(targetIdx-1) as FlowGroupElement;
+					while (FlowGroupElement(targetElement).numChildren)
+					{
+						child = FlowGroupElement(targetElement).getChildAt(0);
+						FlowGroupElement(targetElement).removeChildAt(0);
+						workElem.addChild(child);
+					}
+					targetElement.parent.removeChildAt(targetIdx);
+				}
+			}
+			
+			absStart = origAbsStart;
+			absEnd   = origAbsEnd;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/FlowOperation.as b/textLayout_edit/src/flashx/textLayout/operations/FlowOperation.as
new file mode 100755
index 0000000..06def47
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/FlowOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	//
+	// Considered several ways of doing undo/redo
+	// 1 - object model level - stashing copies of all changed objects in the model and restoring them
+	// 2 - cookies - saving an audit trail of every modified property of the model objects
+	// 3 - operations - each operation creates an object that knows how to do/undo/redo itself
+	// going with # 3 for now
+	//
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.edit.IEditManager;
+	import flashx.undo.IOperation;
+
+	/** 
+	 * The FlowOperation class is the base class for all Text Layout Framework operations. 
+	 * 
+	 * <p>Operations are transformations of a text flow. An Operation class defines the
+	 * logic for performing and undoing the transformation. Operations are executed by an
+	 * edit manager. Most applications do not need to create or manage operations directly
+	 * (unless implementing a custom edit manager).</p>
+	 * 
+	 * <p>When an operation is performed, the edit manager dispatches an Operation object 
+	 * within the FlowOperationEvent object. You can query 
+	 * this Operation object to decide whether or not to allow the operation, to decide whether 
+	 * to perform some other operation as well, or to update related user-interface elements.</p>
+	 * 
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * @see flashx.textLayout.edit.EditManager
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class FlowOperation implements IOperation
+	{
+		/** 
+		 * Arbitrary data associated with an element. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public var userData:*;
+		
+		// uint or null
+		private var _beginGeneration:uint;
+		private var _endGeneration:uint;
+		
+		private var _textFlow:TextFlow;		// target of the operation
+
+		/** 
+		 * Creates the FlowOperation object.
+		 * 
+		 * @param textFlow	The text flow to which this operation is applied.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function FlowOperation(textFlow:TextFlow)
+		{
+			_textFlow = textFlow;
+		}
+		
+		/** 
+		 * The TextFlow object to which this operation is applied.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get textFlow():TextFlow
+		{ return _textFlow; }
+		public function set textFlow(value:TextFlow):void
+		{ _textFlow = value; }
+		
+		/** 
+		 * Executes the operation. 
+		 * 
+		 * <p>This method must be overridden in derived classes. The base class method does nothing.
+		 * You should not call <code>doOperation()</code> directly. The edit manager 
+		 * calls the method when it executes the operation. </p>
+		 * 
+		 * @return Boolean <code>true</code>, if the operation succeeded. Otherwise, <code>false</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function doOperation():Boolean
+		{
+			return false;
+		}
+		
+		/**	
+		 * Reverses the operation. 
+		 * 
+		 * <p>This method must be overridden in derived classes. The base class method does nothing.
+		 * You should not call <code>undo()</code> directly. The edit manager 
+		 * calls the method when it reverses the operation. </p>
+		 * 
+		 * @return The SelectionState object passed to the operation when it was performed. This
+		 * SelectionState object can be the current selection or a selection created specifically
+		 * for the operation. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function undo():SelectionState
+		{
+			return null;
+		}
+		
+		/**	
+		 * Test if this operation be placed on the undo stack.
+		 * 
+		 * @return true means to push the operation onto the undo stack.  false means do not push this operation.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function canUndo():Boolean
+		{ return true; }
+		
+		/**	
+		 * Re-executes the operation. 
+		 * 
+		 * <p>This method must be overridden in derived classes. The base class method does nothing.
+		 * You should not call <code>redo()</code> directly. The edit manager 
+		 * calls the method when it re-executes the operation. </p>
+		 * 
+		 * @return The SelectionState object passed to the operation when it was performed. This
+		 * SelectionState object can be the current selection or a selection created specifically
+		 * for the operation. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function redo():SelectionState
+		{
+			return null;
+		}
+		
+		// Generation numbers
+		
+		/**
+		 * The text flow generation before the operation.
+		 *   
+		 * <p>A generation of 0 indicates that the operation did not complete.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get beginGeneration():uint
+		{ return _beginGeneration; }
+		/** 
+		 * The text flow generation after the operation.
+		 * 
+		 * <p>A generation of 0 indicates that the operation did not complete.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get endGeneration():uint
+		{ return _endGeneration; }
+
+		/** @private */
+		public function performUndo():void
+		{
+			var editManager:IEditManager = textFlow ? textFlow.interactionManager as IEditManager : null;
+			if (editManager != null)
+			{
+				editManager.performUndo(this);
+			}
+		}
+
+		/** @private */
+		public function performRedo():void
+		{
+			var editManager:IEditManager = textFlow ? textFlow.interactionManager as IEditManager : null;
+			if (editManager != null)
+			{
+				editManager.performRedo(this);
+			}
+		}
+		
+		/** @private -- Sets the generation numbers into the operation.  */
+		tlf_internal function setGenerations(beginGeneration:uint,endGeneration:uint):void
+		{
+			_beginGeneration = beginGeneration;
+			_endGeneration   = endGeneration;
+		}
+		
+		/**
+		 * @private
+		 * 
+		 *  Combine this operation with another operation if the result can 
+		 *  be represented as a single operation.  In general, operations cannot be 
+		 *  merged. But sequential inserts or deletes may be mergeable.
+		 * 
+		 *  Merging may occur through updating the properties of the operation
+		 *  on which this method is called, by creating a new operation.
+		 * 
+		 *  @param operation 	The FlowOperation to merge against
+		 *  @return A FlowOperation representing the combined operation if 
+		 *  the merge was successful, null otherwise.
+		 */
+		tlf_internal function merge(operation:FlowOperation):FlowOperation
+		{
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/FlowTextOperation.as b/textLayout_edit/src/flashx/textLayout/operations/FlowTextOperation.as
new file mode 100755
index 0000000..665e7ac
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/FlowTextOperation.as
@@ -0,0 +1,125 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	//
+	// Considered several ways of doing undo/redo
+	// 1 - object model level - stashing copies of all changed objects in the model and restoring them
+	// 2 - cookies - saving an audit trail of every modified property of the model objects
+	// 3 - operations - each operation creates an object that knows how to do/undo/redo itself
+	// going with # 3 for now
+	//
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+
+	/** 
+	 * The FlowTextOperation is the base class for operations that transform a range of text.
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class FlowTextOperation extends FlowOperation
+	{
+		private var _originalSelectionState:SelectionState;
+		private var _absoluteStart:int;
+		private var _absoluteEnd:int;
+
+		/** 
+		 * Creates the FlowTextOperation object.
+		 * 
+		 * @param operationState Specifies the relevant selection. If relevant to the operation, the 
+		 * <code>operationState</code> describes the text range to which this operation applies.
+		 * Otherwise, <code>operationState</code> is used to save the current selection state so that
+		 * it can be restored when the operation is undone.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function FlowTextOperation(operationState:SelectionState)
+		{
+			super(operationState.textFlow);
+			_absoluteStart = operationState.absoluteStart;
+			_absoluteEnd = operationState.absoluteEnd;
+			_originalSelectionState = operationState;
+		}
+				
+		/** 
+		 * The absolute start point of the range of text to which this operation is applied.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get absoluteStart():int
+		{ return _absoluteStart; }
+		public function set absoluteStart(value:int):void
+		{ _absoluteStart = value; }
+		
+		/** 
+		 * The absolute end point of the range of text to which this operation is applied. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get absoluteEnd():int
+		{ return _absoluteEnd; }
+		public function set absoluteEnd(value:int):void
+		{ _absoluteEnd = value; }
+		
+		/** 
+		 * The selection state at the start of the operation. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get originalSelectionState():SelectionState
+		{
+			return _originalSelectionState;
+		}
+		public function set originalSelectionState(value:SelectionState):void
+		{
+			_originalSelectionState = value;
+		}
+		
+		/**	
+		 * @inheritDoc
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		override public function redo():SelectionState
+		{
+			doOperation();
+			return _originalSelectionState;
+		}
+		
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/InsertInlineGraphicOperation.as b/textLayout_edit/src/flashx/textLayout/operations/InsertInlineGraphicOperation.as
new file mode 100755
index 0000000..c560dd9
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/InsertInlineGraphicOperation.as
@@ -0,0 +1,219 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.ElementRange;
+	import flashx.textLayout.edit.ParaEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.SubParagraphGroupElement;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	
+
+	/**
+	 * The InsertInlineGraphicOperation class encapsulates the insertion of an inline
+	 * graphic into a text flow.
+	 *
+	 * @see flashx.textLayout.elements.InlineGraphicElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class InsertInlineGraphicOperation extends FlowTextOperation
+	{
+		private var delSelOp:DeleteTextOperation; 
+		private var _source:Object;
+		private var imageWidth:Object;
+		private var imageHeight:Object;
+		private var _options:Object;
+		private var selPos:int = 0;
+		
+		/** 
+		 * Creates an InsertInlineGraphicsOperation object.
+		 * 
+		 * @param operationState Describes the insertion point. 
+		 * If a range is selected, the operation deletes the contents of that range.
+		 * @param	source	The graphic source (uri string, URLRequest, DisplayObject, or Class of an embedded asset). 
+		 * @param	width	The width to assign (number of pixels, percent, or the string 'auto')
+		 * @param	height	The height to assign (number of pixels, percent, or the string 'auto')
+		 * @param	options	None supported
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		function InsertInlineGraphicOperation(operationState:SelectionState, source:Object, width:Object, height:Object, options:Object = null)
+		{
+			super(operationState);
+			
+			if (absoluteStart != absoluteEnd)
+				delSelOp = new DeleteTextOperation(operationState);
+				
+			_source = source;
+			_options = options;
+			imageWidth = width;
+			imageHeight = height;
+		}
+		
+		/**	
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#source
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+ 		 */
+		public function get source():Object
+		{
+			return _source;
+		}
+		public function set source(value:Object):void
+		{
+			_source = value;
+		}
+
+		/** 
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#width
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get width():Object
+		{
+			return imageWidth;
+		}
+		public function set width(value:Object):void
+		{
+			imageWidth = value;
+		}
+
+		/** 
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#height
+		 * 
+		 * @see flashx.textLayout.InlineGraphicElement#height
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get height():Object
+		{
+			return imageHeight;
+		}
+		public function set height(value:Object):void
+		{
+			imageHeight = value;
+		}
+		
+		/** 
+		 * options are not supported
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get options():Object
+		{
+			return _options;
+		}
+		public function set options(value:Object):void
+		{
+			_options = value;
+		}
+
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			var pointFormat:ITextLayoutFormat;
+			
+			selPos = absoluteStart;
+			if (delSelOp) 
+			{
+				var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+				var deleteFormat:ITextLayoutFormat = new TextLayoutFormat(textFlow.findLeaf(absoluteStart).format);
+				if (delSelOp.doOperation())
+					pointFormat = deleteFormat;
+			}
+			else
+				pointFormat = originalSelectionState.pointFormat;
+				
+			// lean left logic included
+			var range:ElementRange = ElementRange.createElementRange(textFlow,selPos, selPos);		
+			var leafNode:FlowElement = range.firstLeaf;
+			var leafNodeParent:FlowGroupElement = leafNode.parent;
+			while (leafNodeParent is SubParagraphGroupElement)
+			{
+				var subParInsertionPoint:int = selPos - leafNodeParent.getAbsoluteStart();
+				if (((subParInsertionPoint == 0) && (!(leafNodeParent as SubParagraphGroupElement).acceptTextBefore())) ||
+					((subParInsertionPoint == leafNodeParent.textLength) && (!(leafNodeParent as SubParagraphGroupElement).acceptTextAfter())))
+				{
+					leafNodeParent = leafNodeParent.parent;
+				} else {
+					break;
+				}
+			}
+			
+			ParaEdit.createImage(leafNodeParent, selPos - leafNodeParent.getAbsoluteStart(), _source, imageWidth, imageHeight, options, pointFormat);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, 1);
+			
+			return true;
+		}
+	
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var leafNode:FlowElement = textFlow.findLeaf(selPos);
+			var leafNodeParent:FlowGroupElement = leafNode.parent;
+			var elementIdx:int = leafNode.parent.getChildIndex(leafNode);
+			leafNodeParent.replaceChildren(elementIdx, elementIdx + 1, null);			
+					
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -1);
+
+			return delSelOp ? delSelOp.undo() : originalSelectionState; 
+		}
+
+		/**
+		 * Re-executes the operation after it has been undone.
+		 * 
+		 * <p>This function is called by the edit manager, when necessary.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public override function redo():SelectionState
+		{ 
+			doOperation();
+			return new SelectionState(textFlow,selPos+1,selPos+1,null);
+		}
+
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/InsertTextOperation.as b/textLayout_edit/src/flashx/textLayout/operations/InsertTextOperation.as
new file mode 100755
index 0000000..ecaef8d
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/InsertTextOperation.as
@@ -0,0 +1,306 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.ElementRange;
+	import flashx.textLayout.edit.ParaEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TCYElement;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+
+	/**
+	 * The InsertTextOperation class encapsulates a text insertion operation.
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class InsertTextOperation extends FlowTextOperation
+	{
+		private var _deleteSelectionState:SelectionState;
+		private var delSelOp:DeleteTextOperation = null; 
+		/** @private - this should be private but too late for code changes on Labs */
+		public var _text:String;
+		private var adjustedForInsert:Boolean = false;
+		
+		private var _characterFormat:ITextLayoutFormat;
+			
+		/** 
+		 * Creates an InsertTextOperation object.
+		 * 
+		 * @param operationState Describes the insertion point or range of text.
+		 * @param text The string to insert.
+		 * @param deleteSelectionState Describes the range of text to delete before doing insertion, 
+		 * if different than the range described by <code>operationState</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */	
+		public function InsertTextOperation(operationState:SelectionState, text:String, deleteSelectionState:SelectionState = null)
+		{
+			super(operationState);
+			
+			_characterFormat = operationState.pointFormat;
+			_text = text;
+			
+			initialize(deleteSelectionState);
+		}
+		
+		private function initialize(deleteSelectionState:SelectionState):void
+		{	
+			if (deleteSelectionState == null)
+				deleteSelectionState = originalSelectionState;
+			if (deleteSelectionState.anchorPosition != deleteSelectionState.activePosition)
+			{
+				_deleteSelectionState = deleteSelectionState;
+				delSelOp = new DeleteTextOperation(_deleteSelectionState);
+			}
+		}
+		
+		/** 
+		 * The text inserted by this operation. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get text():String
+		{
+			return _text;
+		}
+		public function set text(value:String):void
+		{
+			_text = value;
+		}
+		
+		/** 
+		 * The text deleted by this operation, if any.
+		 * 
+		 * <p><code>null</code> if no text is deleted.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get deleteSelectionState():SelectionState
+		{
+			return _deleteSelectionState;
+		}
+		public function set deleteSelectionState(value:SelectionState):void
+		{
+			_deleteSelectionState = value;
+		}
+		
+		/** 
+		 * The character format applied to the inserted text.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get characterFormat():ITextLayoutFormat
+		{
+			return _characterFormat;
+		}
+		public function set characterFormat(value:ITextLayoutFormat):void
+		{
+			_characterFormat = new TextLayoutFormat(value);
+		}
+		
+		private function doInternal():void
+		{
+			var leafEl:FlowLeafElement = textFlow.findLeaf(absoluteStart);
+			var tcyEl:TCYElement = null;
+			
+			if(leafEl is InlineGraphicElement && leafEl.parent is TCYElement)
+			{
+				tcyEl = leafEl.parent as TCYElement;
+			}
+			
+			if (delSelOp != null) {	
+				var deleteFormat:ITextLayoutFormat = new TextLayoutFormat(textFlow.findLeaf(absoluteStart).format);
+				if (delSelOp.doOperation())		// figure out what to do here
+				{
+					//do not change characterFormat if user specified one already
+					if ((characterFormat == null) && (absoluteStart < absoluteEnd))
+					{
+						_characterFormat = deleteFormat;
+					} 
+					else 
+					{
+						if (leafEl.textLength == 0) 
+						{
+							var pos:int = leafEl.parent.getChildIndex(leafEl);
+							leafEl.parent.replaceChildren(pos, pos + 1, null);
+						}
+					}
+					
+					if(tcyEl && tcyEl.numChildren == 0)
+					{
+						leafEl = new SpanElement();
+						tcyEl.replaceChildren(0,0,leafEl);
+					}
+				} 
+			} 
+			
+			// Wasteful, but it gives us the leanLeft logic for insert - which we only want to do if this is a point selection.
+			
+			var range:ElementRange;
+			var useExistingLeaf:Boolean = false;
+			// favor using leaf we have if it's valid (i.e., it has a paragraph in its parent chain and it is still inside a TextFlow)
+			if (absoluteStart >= absoluteEnd || leafEl.getParagraph() == null || leafEl.getTextFlow() == null)
+			{
+				range = ElementRange.createElementRange(textFlow,absoluteStart, absoluteStart);
+			}
+			else
+			{
+				range = new ElementRange();
+				range.firstParagraph = leafEl.getParagraph();
+				range.firstLeaf = leafEl;
+				useExistingLeaf = true;
+			}
+			var paraSelBegIdx:int = absoluteStart-range.firstParagraph.getAbsoluteStart();
+			
+			// force insert to use the leaf given if we have a good one
+			ParaEdit.insertText(range.firstParagraph, range.firstLeaf, paraSelBegIdx, _text, useExistingLeaf);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, _text.length);
+			
+			if (_characterFormat && !TextLayoutFormat.isEqual(_characterFormat, range.firstLeaf.format))
+				ParaEdit.applyTextStyleChange(textFlow,absoluteStart,absoluteStart+_text.length,_characterFormat,null);
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			doInternal();
+			if (originalSelectionState.selectionManagerOperationState && textFlow.interactionManager)
+			{
+				var state:SelectionState = textFlow.interactionManager.getSelectionState();
+				if (state.pointFormat)
+				{
+					state.pointFormat = null;
+					textFlow.interactionManager.setSelectionState(state);
+				}
+			}
+			return true;
+		}
+	
+		/** @private */
+		public override function undo():SelectionState
+		{ 
+			var para:ParagraphElement = textFlow.findAbsoluteParagraph(absoluteStart);
+			// paragraph relative offset - into the store
+			var paraSelBegIdx:int = absoluteStart-para.getAbsoluteStart();
+
+			ParaEdit.deleteText(para, paraSelBegIdx, _text.length);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -_text.length);
+			
+			var newSelectionState:SelectionState = originalSelectionState;
+			if (delSelOp != null)
+			{
+				newSelectionState = delSelOp.undo();
+			}
+			
+			if (adjustedForInsert)
+			{
+				var newBegIdx:int = newSelectionState.anchorPosition;
+				var newEndIdx:int = newSelectionState.activePosition;
+				if (newEndIdx > newBegIdx) newEndIdx--;
+				else newBegIdx--;
+				
+				if (absoluteStart < absoluteEnd)
+				{
+					return new SelectionState(textFlow, newBegIdx, newEndIdx, newSelectionState.pointFormat);
+				}
+				else
+				{
+					return new SelectionState(textFlow, newBegIdx, newEndIdx, originalSelectionState.pointFormat);
+				}
+			}
+			return originalSelectionState;
+		}
+		
+		/**
+		 * Re-executes the operation after it has been undone.
+		 * 
+		 * <p>This function is called by the edit manager, when necessary.</p>
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public override function redo():SelectionState
+		{ 
+			doInternal();
+			return new SelectionState(textFlow,absoluteStart+_text.length,absoluteStart+_text.length,null);
+		}
+
+		/** @private */
+		tlf_internal override function merge(op2:FlowOperation):FlowOperation
+		{
+			if (absoluteStart < absoluteEnd)
+				return null;
+			if (this.endGeneration != op2.beginGeneration)
+				return null;
+			// We are assuming here that these operations are contiguous, because
+			// SelectionManager doesn't try to merge operations if the selection
+			// has changed
+			var insertOp:InsertTextOperation = null;
+			if (op2 is InsertTextOperation)
+				insertOp = op2 as InsertTextOperation;
+			if (insertOp)
+			{
+				if (insertOp.deleteSelectionState != null || deleteSelectionState != null)
+					return null;
+				if ((insertOp.originalSelectionState.pointFormat == null) && (originalSelectionState.pointFormat != null))
+					return null;
+				if ((originalSelectionState.pointFormat == null) && (insertOp.originalSelectionState.pointFormat != null))
+					return null;
+				if (originalSelectionState.absoluteStart + _text.length != insertOp.originalSelectionState.absoluteStart)
+					return null;
+				if (((originalSelectionState.pointFormat == null) && (insertOp.originalSelectionState.pointFormat == null)) ||
+					(TextLayoutFormat.isEqual(originalSelectionState.pointFormat, insertOp.originalSelectionState.pointFormat)))
+					_text += insertOp.text;
+				else
+					return null;
+				setGenerations(beginGeneration,insertOp.endGeneration);
+				return this;
+			}
+			
+			if (op2 is SplitParagraphOperation)
+				return new CompositeOperation([this,op2]);
+
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/ModifyInlineGraphicOperation.as b/textLayout_edit/src/flashx/textLayout/operations/ModifyInlineGraphicOperation.as
new file mode 100755
index 0000000..9537853
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/ModifyInlineGraphicOperation.as
@@ -0,0 +1,171 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+
+	/**
+	 * The InsertInlineGraphicOperation class encapsulates the modification of an existing inline graphic.
+	 *
+	 * @see flashx.textLayout.elements.InlineGraphicElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class ModifyInlineGraphicOperation extends FlowTextOperation
+	{ 
+		private var _source:Object;
+		private var imageWidth:Object;
+		private var imageHeight:Object;
+		private var _options:Object;
+		private var oldImage:FlowElement;
+		private var selPos:int = 0;
+		
+		/** 
+		 * Creates a ModifyInlineGraphicsOperation object.
+		 * 
+		 * @param operationState Describes the insertion point. 
+		 * If a range is selected, the operation deletes the contents of that range.
+		 * @param	source	The graphic source (uri string, URLRequest, DisplayObject, or Class of an embedded asset). 
+		 * @param	width	The width to assign (number of pixels, percent, or the string 'auto')
+		 * @param	height	The height to assign (number of pixels, percent, or the string 'auto')
+		 * @param	options	None supported
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		function ModifyInlineGraphicOperation(operationState:SelectionState, source:Object, width:Object, height:Object, options:Object = null)
+		{
+			super(operationState);
+							
+			_source = source;
+			_options = options;
+			imageWidth = width;
+			imageHeight = height;
+		}
+		
+		/**	
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#source
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+ 		 */
+		public function get source():Object
+		{
+			return _source;
+		}
+		public function set source(value:Object):void
+		{
+			_source = value;
+		}
+
+		/** 
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#width
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get width():Object
+		{
+			return imageWidth;
+		}
+		public function set width(value:Object):void
+		{
+			imageWidth = value;
+		}
+
+		/** 
+		 * @copy flashx.textLayout.elements.InlineGraphicElement#height
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get height():Object
+		{
+			return imageHeight;
+		}
+		public function set height(value:Object):void
+		{
+			imageHeight = value;
+		}
+		
+		/** 
+		 * options are not supported
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get options():Object
+		{
+			return _options;
+		}
+		public function set options(value:Object):void
+		{
+			_options = value;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			selPos = absoluteStart;
+			var img:InlineGraphicElement = textFlow.findLeaf(selPos) as InlineGraphicElement;
+			if (img)
+			{
+				oldImage = img.shallowCopy(0,1);
+				// only update changed things
+				if (img.width != imageWidth)
+					img.width = imageWidth;
+				if (img.height != imageHeight)
+					img.height = imageHeight;
+				if (img.source != _source)
+					img.source = _source;
+				if (options && img.float != options.toString())
+					img.float = options.toString();
+			}
+			
+			return true;	
+		}
+	
+		/** @private */
+		public override function undo():SelectionState
+		{
+			var leafNode:FlowElement = textFlow.findLeaf(selPos);
+			var leafNodeParent:FlowGroupElement = leafNode.parent;
+			var elementIdx:int = leafNode.parent.getChildIndex(leafNode);
+			leafNodeParent.replaceChildren(elementIdx, elementIdx + 1, oldImage);			
+
+			return originalSelectionState; 
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/PasteOperation.as b/textLayout_edit/src/flashx/textLayout/operations/PasteOperation.as
new file mode 100755
index 0000000..0554f6f
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/PasteOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.edit.TextFlowEdit;
+	import flashx.textLayout.edit.TextScrap;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+
+
+	use namespace tlf_internal;
+
+
+	/**
+	 * The PasteOperation class encapsulates a paste operation.
+	 *
+	 * <p>The specified range is replaced by the new content.</p>
+	 * 
+	 * <p><b>Note:</b> The edit manager is responsible for copying the 
+	 * contents of the clipboard.</p>
+	 * 
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */			
+	public class PasteOperation extends FlowTextOperation
+	{
+		private var _textScrap:TextScrap;
+		private var _tScrapUnderSelection:TextScrap;
+		private var _numCharsAdded:int = 0;
+		
+		/** 
+		 * Creates a PasteOperation object.
+		 * 
+		 * @param operationState Describes the insertion point or a range of text 
+		 * to replace.
+		 * @param textScrap The content to paste into the text flow.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function PasteOperation(operationState:SelectionState, textScrap:TextScrap)
+		{
+			super(operationState);
+			_textScrap = textScrap;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{
+			if (_textScrap != null)
+			{
+				_tScrapUnderSelection = TextFlowEdit.createTextScrap(originalSelectionState.textFlow, originalSelectionState.absoluteStart, originalSelectionState.absoluteEnd);
+				internalDoOperation();
+			}
+			return true;	
+		}
+		
+		private function internalDoOperation():void
+		{
+			if (absoluteStart != absoluteEnd)	
+			{
+				TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteEnd, null);
+				if (textFlow.interactionManager)
+					textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, absoluteStart - absoluteEnd);
+			}
+			
+			var nextInsertPosition:int = TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteStart, _textScrap);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, nextInsertPosition - absoluteStart);				
+			_numCharsAdded = (nextInsertPosition - absoluteStart) /*- (absoluteEnd - absoluteStart) */;
+		}
+		
+		/** @private */
+		public override function undo():SelectionState
+		{
+			if (_textScrap != null)
+			{
+				TextFlowEdit.replaceRange(textFlow, absoluteStart, absoluteStart + _numCharsAdded, _tScrapUnderSelection);
+				if (textFlow.interactionManager)
+					textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -_numCharsAdded);
+			}
+			return originalSelectionState;	
+		}
+	
+		/** @private */
+		public override function redo():SelectionState
+		{
+			if (_textScrap != null)
+				internalDoOperation();								
+			return new SelectionState(textFlow, absoluteStart + _numCharsAdded, absoluteStart + _numCharsAdded,null);	
+		}		
+
+		/** 
+		 * textScrap the text being pasted
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get textScrap():TextScrap
+		{ return _textScrap; }
+		public function set textScrap(val:TextScrap):void
+		{ _textScrap = val; }		
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/RedoOperation.as b/textLayout_edit/src/flashx/textLayout/operations/RedoOperation.as
new file mode 100755
index 0000000..3fbb8c3
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/RedoOperation.as
@@ -0,0 +1,74 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	/** 
+	 * The RedoOperation class encapsulates a redo operation.
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @includeExample examples\RedoOperation_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class RedoOperation extends FlowOperation
+	{
+		private var _operation:FlowOperation;	/** Operation to be undone - here so listeners on FlowOperationEvent can see. */
+		
+		/** 
+		 * Creates a RedoOperation object.
+		 * 
+		 * @param operation	The operation to redo.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function RedoOperation(operation:FlowOperation)
+		{ 
+			super(operation.textFlow);
+			_operation = operation;
+		}
+
+
+		/** 
+		 * The operation to redo.
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		*/
+		public function get operation():FlowOperation
+		{
+			return _operation;
+		}
+		public function set operation(value:FlowOperation):void
+		{
+			_operation = value;
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/operations/SplitParagraphOperation.as b/textLayout_edit/src/flashx/textLayout/operations/SplitParagraphOperation.as
new file mode 100755
index 0000000..346e0b7
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/SplitParagraphOperation.as
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.operations
+{
+	import flash.utils.getQualifiedClassName;
+	
+	import flashx.textLayout.edit.ParaEdit;
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.SpanElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.TextLayoutFormat;
+	import flashx.textLayout.formats.ITextLayoutFormat;
+	import flashx.textLayout.tlf_internal;
+
+
+	use namespace tlf_internal;
+
+
+	/**
+	 * The SplitParagraphOperation class encapsulates a change that splits a paragraph into two elements.
+	 *
+	 * <p>The operation creates a new paragraph containing the text from 
+	 * the specified position to the end of the paragraph. If a range of text is specified, the text 
+	 * in the range is deleted first.</p>
+	 * 
+	 * @see flashx.textLayout.elements.ParagraphElement
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */			
+	public class SplitParagraphOperation extends FlowTextOperation
+	{
+		private var delSelOp:DeleteTextOperation;
+		private var _characterFormat:ITextLayoutFormat;
+		
+		/** 
+		 * Creates a SplitParagraphOperation object.
+		 * 
+		 * @param operationState Describes the point at which to split the paragraph.
+		 * If a range of text is specified, the contents of the range are deleted.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		function SplitParagraphOperation(operationState:SelectionState)
+		{
+			super(operationState);
+			characterFormat = operationState.pointFormat;
+		}
+		
+		/** 
+		 * The format applied to the new empty paragraph when a paragraph is split at the end.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		private function get characterFormat():ITextLayoutFormat
+		{
+			return _characterFormat;
+		}
+		private function set characterFormat(value:ITextLayoutFormat):void
+		{
+			_characterFormat = value ? new TextLayoutFormat(value) : null;
+		}
+		
+		/** @private */
+		public override function doOperation():Boolean
+		{ 
+			if (absoluteStart < absoluteEnd)
+			{
+				delSelOp = new DeleteTextOperation(originalSelectionState);
+				delSelOp.doOperation();
+			}
+			
+			var para:ParagraphElement = textFlow.findAbsoluteParagraph(absoluteStart);
+			
+			// paragraph relative offset - into the store
+			var paraSelBegIdx:int = absoluteStart-para.getAbsoluteStart();
+			
+			var nextPara:ParagraphElement = ParaEdit.splitParagraph(para, paraSelBegIdx, _characterFormat);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, 1);
+
+			// splitParagraph guarantees these exist
+			var lastParaLeaf:FlowLeafElement = para.getLastLeaf(); 
+			if (lastParaLeaf != null && lastParaLeaf.textLength == 1)
+			{
+				//if the lastParaLeaf is only a newline, you really want the span right before
+				var elementIdx:int = lastParaLeaf.parent.getChildIndex(lastParaLeaf);
+				if (elementIdx > 0)
+				{
+					var prevSpan:SpanElement = lastParaLeaf.parent.getChildAt(elementIdx - 1) as SpanElement;
+					if (prevSpan != null) lastParaLeaf = prevSpan;
+				}
+			}
+			
+			var firstNextParaLeaf:FlowLeafElement = nextPara.getFirstLeaf();
+			
+			var newCharAttrs:TextLayoutFormat; // Point format for new selection position
+			if (getQualifiedClassName(lastParaLeaf.parent) != getQualifiedClassName(firstNextParaLeaf.parent))
+			{
+				// Reset it; no easy way to migrate point format when parent types differ
+				newCharAttrs = new TextLayoutFormat();
+			} 
+			else
+			{
+				// 1. Convert to absolute (position-independent) value by concatenating with the actual attribute of para's last leaf
+				newCharAttrs = new TextLayoutFormat(_characterFormat);
+				
+				if (nextPara.textLength == 1)
+				{
+					//we have a completely new paragraph.  Just append on the character
+					//attributes of the last leaf and stop.
+					if (lastParaLeaf.format != null)
+					{
+						newCharAttrs.concat(lastParaLeaf.format);
+					}
+				}
+				else
+				{
+					newCharAttrs.concat(lastParaLeaf.computedFormat);
+					
+					// 2. Convert to a relative value (dependent on the new position) by removing attributes 
+					// that match the actual  attributes of nextPar's first leaf 
+					newCharAttrs.removeMatching(firstNextParaLeaf.computedFormat);
+				}
+			}		
+
+			return true;
+		}
+	
+		/** @private */
+		public override function undo():SelectionState
+		{ 
+			var para:ParagraphElement = textFlow.findAbsoluteParagraph(absoluteStart);
+			ParaEdit.mergeParagraphWithNext(para);
+			if (textFlow.interactionManager)
+				textFlow.interactionManager.notifyInsertOrDelete(absoluteStart, -1);
+			
+			return absoluteStart < absoluteEnd ? delSelOp.undo() : originalSelectionState;
+		}
+		
+		/** @private */
+		tlf_internal override function merge(operation:FlowOperation):FlowOperation
+		{
+			if (this.endGeneration != operation.beginGeneration)
+				return null;
+			// TODO we could probably do something a bit more efficient for a backspace
+			if ((operation is SplitParagraphOperation) || (operation is InsertTextOperation))
+				return new CompositeOperation([this,operation]);
+			return null;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_edit/src/flashx/textLayout/operations/UndoOperation.as b/textLayout_edit/src/flashx/textLayout/operations/UndoOperation.as
new file mode 100755
index 0000000..623b6ac
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/operations/UndoOperation.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 flashx.textLayout.operations
+{
+	import flashx.textLayout.edit.SelectionState;
+	import flashx.textLayout.tlf_internal;
+
+	use namespace tlf_internal;
+
+	/** 
+	 * The UndoOperation class encapsulates an undo operation.
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 * @see flashx.textLayout.events.FlowOperationEvent
+	 * 
+	 * @includeExample examples\UndoOperation_example.as -noswf
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0 
+	 */
+	public class UndoOperation extends FlowOperation
+	{
+		private var _operation:FlowOperation;	/** Operation to be undone - here so listeners on FlowOperationEvent can see. */
+		
+		/** 
+		 * Creates an UndoOperation object.
+		 * 
+		 * @param op	The operation to undo.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0 
+		 */
+		public function UndoOperation(op:FlowOperation)
+		{ 
+			super(null);
+			_operation = op;
+		}
+		
+		/** 
+		 * The operation to undo. 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0 
+		 */
+		public function get operation():FlowOperation
+		{
+			return _operation;
+		}
+		public function set operation(value:FlowOperation):void
+		{
+			_operation = value;
+		}
+	}
+}
diff --git a/textLayout_edit/src/flashx/textLayout/utils/NavigationUtil.as b/textLayout_edit/src/flashx/textLayout/utils/NavigationUtil.as
new file mode 100755
index 0000000..faf5770
--- /dev/null
+++ b/textLayout_edit/src/flashx/textLayout/utils/NavigationUtil.as
@@ -0,0 +1,1220 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.utils
+{
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextLine;
+	import flash.text.engine.TextRotation;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.TextFlowLine;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.ScrollPolicy;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.elements.TextRange;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Direction;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+
+	/** 
+	 * Utilities for manipulating a TextRange 
+	 * The methods of this class are static and must be called using
+	 * the syntax <code>NavigationUtil.method(<em>parameter</em>)</code>.
+	 *
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+	 * @langversion 3.0
+	 */
+	public final class NavigationUtil 
+	{
+		private static function validateTextRange(range:TextRange):Boolean
+		{ return range.textFlow != null && range.anchorPosition != -1 && range.activePosition != -1; }
+		
+		private static function doIncrement(flowRoot:TextFlow, pos:int, incrementer:Function):int
+		{
+			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(pos);
+			return incrementer(flowRoot, para, pos, para.getAbsoluteStart());			
+		}
+		
+		private static function previousAtomHelper(flowRoot:TextFlow, para:ParagraphElement, pos:int, paraStart:int):int
+		{
+			if (pos - paraStart == 0)
+				return (pos > 0) ? pos - 1 : 0;
+			return para.findPreviousAtomBoundary(pos - paraStart) + paraStart;
+		}
+		
+		/** 
+		 * Returns the absolute position of the previous atom. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function previousAtomPosition(flowRoot:TextFlow, absolutePos:int):int
+		{
+			return doIncrement(flowRoot,absolutePos,previousAtomHelper);
+		}
+	
+		private static function nextAtomHelper(flowRoot:TextFlow, para:ParagraphElement, pos:int, paraStart:int):int
+		{
+			if (pos - paraStart == para.textLength - 1)
+				return Math.min(flowRoot.textLength - 1, pos + 1);
+			return para.findNextAtomBoundary(pos - paraStart) + paraStart;
+		}
+		
+		/** 
+		 * Returns the absolute position of the next atom.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function nextAtomPosition(flowRoot:TextFlow, absolutePos:int):int
+		{
+			return doIncrement(flowRoot,absolutePos,nextAtomHelper);
+		}
+	
+		/** 
+		 * Returns absolute position of the beginning of the previous word.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function previousWordPosition(flowRoot:TextFlow, absolutePos:int):int
+		{
+			if (isOverset(flowRoot, absolutePos))
+				return endOfLastController(flowRoot);
+			
+			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(absolutePos);
+			var paraStart:int = para.getAbsoluteStart();
+			
+			var prevWordPos:int = absolutePos - paraStart;
+			var nextWordPos:int = 0;
+			if (absolutePos - paraStart == 0)
+				return (absolutePos > 0) ? absolutePos - 1 : 0;
+			do
+			{
+				nextWordPos = para.findPreviousWordBoundary(prevWordPos);
+				if (prevWordPos == nextWordPos) prevWordPos = para.findPreviousWordBoundary(prevWordPos - 1);
+				else prevWordPos = nextWordPos;
+			} while (prevWordPos > 0 && CharacterUtil.isWhitespace(para.getCharCodeAtPosition(prevWordPos)));
+			return prevWordPos + paraStart;
+		}
+	
+		/** 
+		 * Returns the absolute position of the beginning of the next word.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		public static function nextWordPosition(flowRoot:TextFlow, absolutePos:int):int
+		{
+			var para:ParagraphElement = flowRoot.findAbsoluteParagraph(absolutePos);
+			var paraStart:int = para.getAbsoluteStart();
+			
+			var nextWordPos:int = absolutePos - paraStart;
+			
+			if (absolutePos - paraStart == para.textLength - 1)
+				return Math.min(flowRoot.textLength - 1, absolutePos + 1);
+			do
+			{
+				nextWordPos = para.findNextWordBoundary(nextWordPos);
+			} while (nextWordPos < (para.textLength - 1) && CharacterUtil.isWhitespace(para.getCharCodeAtPosition(nextWordPos)))
+			return nextWordPos + paraStart;
+		}
+		
+		/** @private */
+		static tlf_internal function updateStartIfInReadOnlyElement(textFlow:TextFlow, idx:int):int
+		{
+			return idx;
+		}
+		
+		/** @private */
+		static tlf_internal function updateEndIfInReadOnlyElement(textFlow:TextFlow, idx:int):int
+		{
+			return idx; 
+		}
+		
+		static private function moveForwardHelper(range:TextRange, extendSelection:Boolean, incrementor:Function):Boolean
+		{
+			var textFlow:TextFlow = range.textFlow;
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+				
+			if (extendSelection) 
+				endIdx = incrementor(textFlow, endIdx);
+			else {
+				if (begIdx == endIdx) //no selection, just move insertion point
+				{
+					begIdx = incrementor(textFlow, begIdx);
+					endIdx = begIdx;
+				}
+				else if (endIdx > begIdx) //change selection to insertion point
+					begIdx = endIdx;
+				else
+					endIdx = begIdx;
+			}
+			
+			if (begIdx == endIdx)
+			{
+				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			} 
+					
+			if (!extendSelection && (range.anchorPosition == begIdx) && (range.activePosition == endIdx))
+			{
+				if (begIdx < endIdx)
+				{
+					begIdx = Math.min(endIdx + 1, textFlow.textLength - 1);
+					endIdx = begIdx;
+				}else {
+					endIdx = Math.min(begIdx + 1, textFlow.textLength - 1);
+					begIdx = endIdx;
+				}	
+			}
+			return range.updateRange(begIdx,endIdx);							 	
+		}
+		
+		static private function moveBackwardHelper(range:TextRange, extendSelection:Boolean, incrementor:Function):Boolean
+		{
+			var textFlow:TextFlow = range.textFlow;
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+				
+			if (extendSelection)	//shift key is pressed 
+				endIdx = incrementor(textFlow, endIdx);
+			else {
+				if (begIdx == endIdx) //no selection, just move insertion point
+				{
+					begIdx = incrementor(textFlow, begIdx);
+					endIdx = begIdx;
+				}
+				else if (endIdx > begIdx) //change selection to insertion point
+					endIdx = begIdx;
+				else
+					begIdx = endIdx;
+			}
+					
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} 
+					
+			if (!extendSelection && (range.anchorPosition == begIdx) && (range.activePosition == endIdx))
+			{
+				if (begIdx < endIdx)
+				{
+					endIdx = Math.max(begIdx - 1, 0);
+					begIdx = endIdx;
+				}else {
+					begIdx = Math.max(endIdx - 1, 0);
+					endIdx = begIdx;
+				}	
+			}
+			return range.updateRange(begIdx,endIdx);
+		 }
+		
+		/**
+		 * Sets the TextRange forward by one character.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 
+		static public function nextCharacter(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (validateTextRange(range))
+			{
+				if (!adjustForOversetForward(range))
+					moveForwardHelper(range, extendSelection, nextAtomPosition);
+				return true;
+			}
+		 	return false;
+		}
+		 
+		/**
+		 * Sets the TextRange backward by one character.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 
+		static public function previousCharacter(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (validateTextRange(range))
+			{
+				if (!adjustForOversetBack(range))
+					moveBackwardHelper(range, extendSelection, previousAtomPosition);
+				return true;
+			} 
+			return false;
+		} 
+		/**
+		 * Sets the TextRange forward by one word.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 
+		static public function nextWord(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (validateTextRange(range))
+			{
+				if (!adjustForOversetForward(range))
+					moveForwardHelper(range, extendSelection, nextWordPosition);
+				return true;
+			}
+			return false;
+		}
+		 
+		/**
+		 * Sets the TextRange backward by one word.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 
+		static public function previousWord(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (validateTextRange(range))
+			{
+				if (!adjustForOversetBack(range))
+		 			moveBackwardHelper(range, extendSelection, previousWordPosition);
+		 		return true;
+		 	}
+		 	return false;
+		} 
+		/**
+		 * Sets the TextRange down one line
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 
+		static public function nextLine(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+		
+			if (adjustForOversetForward(range))
+				return true;
+				
+			var textFlow:TextFlow = range.textFlow;
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			var limitIdx:int = endOfLastController(textFlow);
+			
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var isRTLDirection:Boolean = (textFlow.computedFormat.direction == Direction.RTL);			
+
+			if (curLine < textFlow.flowComposer.numLines-1)	//create, expand or shrink the selection
+			{
+				var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
+				var lineStart:int = curTextFlowLine.absoluteStart;
+				var lineDelta:int = endIdx - lineStart;
+				var currentTextLine:TextLine = curTextFlowLine.getTextLine(true);
+				var para:ParagraphElement = curTextFlowLine.paragraph;
+				var atomIndex:int = currentTextLine.getAtomIndexAtCharIndex(endIdx - para.getAbsoluteStart());
+				var bidiRightToLeft:Boolean = ((currentTextLine.getAtomBidiLevel(atomIndex) % 2) != 0); 
+				var curPosRect:Rectangle = currentTextLine.getAtomBounds(atomIndex);
+				var currentTextLineX:Number = currentTextLine.x;
+				var curPosRectLeft:Number = curPosRect.left;
+				var curPosRectRight:Number = curPosRect.right;
+				if(textFlow.computedFormat.blockProgression == BlockProgression.RL)
+				{
+					currentTextLineX = currentTextLine.y;
+					curPosRectLeft = curPosRect.top;
+					curPosRectRight = curPosRect.bottom;
+				}
+				
+				//find the atom
+				var globalPoint:Point = new Point();				
+						
+				if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+				{
+					if (!isRTLDirection)
+						globalPoint.x = curPosRect.left;
+					else
+						globalPoint.x = curPosRect.right;
+					globalPoint.y = 0;
+				} else {						
+					globalPoint.x = 0;
+					if (!isRTLDirection)
+						globalPoint.y = curPosRect.top;
+					else
+						globalPoint.y = curPosRect.bottom;
+				}
+				
+				globalPoint = currentTextLine.localToGlobal(globalPoint);
+				
+				//at this point, we have the global point of our current position.  Now adjust x or y to the
+				//baseline of the next line.
+				var nextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine + 1);
+				if (nextFlowLine.absoluteStart >= limitIdx)
+				{
+					if (!extendSelection)
+						range.anchorPosition = textFlow.textLength-1;
+					range.activePosition = textFlow.textLength-1;
+					return true;
+				}
+				
+				
+				// get the last container so that we can make sure the previous line is in view.
+				var controller:ContainerController = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
+				var firstPosInContainer:int = controller.absoluteStart;
+				var lastPosInContainer:int = firstPosInContainer + controller.textLength;
+				if ((nextFlowLine.absoluteStart >= firstPosInContainer) && (nextFlowLine.absoluteStart < lastPosInContainer))
+				{
+					if (nextFlowLine.isDamaged())
+					{
+						textFlow.flowComposer.composeToPosition(nextFlowLine.absoluteStart+1);
+						nextFlowLine = textFlow.flowComposer.getLineAt(curLine + 1);
+					}
+					controller.scrollToRange(nextFlowLine.absoluteStart, nextFlowLine.absoluteStart + nextFlowLine.textLength - 1);
+				}
+				
+				var nextTextLine:TextLine = nextFlowLine.getTextLine(true);
+				if (nextFlowLine.controller == curTextFlowLine.controller)
+				{				
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+					{
+						globalPoint.y += (nextFlowLine.y - curTextFlowLine.y);
+					} else {
+						globalPoint.x -= (curTextFlowLine.x - nextFlowLine.x);
+					}
+				} else {
+					var firstAtomRect:Rectangle = nextTextLine.getAtomBounds(0);
+					var firstAtomPoint:Point = new Point();
+					firstAtomPoint.x = firstAtomRect.left;
+					firstAtomPoint.y = 0;
+					firstAtomPoint = nextTextLine.localToGlobal(firstAtomPoint);
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+					{
+						globalPoint.x += nextFlowLine.controller.container.x;
+						globalPoint.y = firstAtomPoint.y;
+					} else {
+						globalPoint.x = firstAtomPoint.x;
+						globalPoint.y += nextFlowLine.controller.container.y; 
+					}					
+				} 
+				
+				atomIndex = nextTextLine.getAtomIndexAtPoint(globalPoint.x,globalPoint.y);
+				if (atomIndex == -1)
+				{
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL) {
+						if (!bidiRightToLeft) {
+							endIdx = (globalPoint.x <= nextTextLine.x) ? nextFlowLine.absoluteStart : (nextFlowLine.absoluteStart + nextFlowLine.textLength - 1);
+						} else {
+							endIdx = (globalPoint.x <= nextTextLine.x) ? (nextFlowLine.absoluteStart + nextFlowLine.textLength - 1) : nextFlowLine.absoluteStart;							
+						}
+					} else {
+						if (!bidiRightToLeft) {
+							endIdx = (globalPoint.y <= nextTextLine.y) ? nextFlowLine.absoluteStart : (nextFlowLine.absoluteStart + nextFlowLine.textLength - 1);							
+						} else {
+							endIdx = (globalPoint.y <= nextTextLine.y) ? (nextFlowLine.absoluteStart + nextFlowLine.textLength - 1) : nextFlowLine.absoluteStart;
+						}
+					}
+				} else {
+					// get the character box and if check we are past the middle select past this character. 
+					var glyphRect:Rectangle = nextTextLine.getAtomBounds(atomIndex);
+					var leanRight:Boolean = false;
+					if(glyphRect)
+					{	
+						//if this is TTB and NOT TCY determine lean based on Y coordinates...
+						var glyphGlobalPoint:Point = new Point();
+						glyphGlobalPoint.x = glyphRect.x;
+						glyphGlobalPoint.y = glyphRect.y;
+						glyphGlobalPoint = nextTextLine.localToGlobal(glyphGlobalPoint);
+						
+						if((textFlow.computedFormat.blockProgression == BlockProgression.RL) && nextTextLine.getAtomTextRotation(atomIndex) != TextRotation.ROTATE_0)
+							leanRight = (globalPoint.y > (glyphGlobalPoint.y + glyphRect.height/2));
+						else //use X..
+							leanRight = (globalPoint.x > (glyphGlobalPoint.x + glyphRect.width/2));
+					}
+			
+					var paraSelectionIdx:int;
+					if ((nextTextLine.getAtomBidiLevel(atomIndex) % 2) != 0) // Right to left case, right is "start" unicode
+						paraSelectionIdx = leanRight ? nextTextLine.getAtomTextBlockBeginIndex(atomIndex) : nextTextLine.getAtomTextBlockEndIndex(atomIndex);
+					else  {// Left to right case, right is "end" unicode
+						if (isRTLDirection) {
+							if ((leanRight == false) && (atomIndex > 0))
+							{
+								paraSelectionIdx = nextTextLine.getAtomTextBlockBeginIndex(atomIndex - 1);	
+							} else {
+								paraSelectionIdx = nextTextLine.getAtomTextBlockBeginIndex(atomIndex);
+							}
+						} else {
+							paraSelectionIdx = leanRight ? nextTextLine.getAtomTextBlockEndIndex(atomIndex) : nextTextLine.getAtomTextBlockBeginIndex(atomIndex);							
+						}
+					}
+					endIdx = nextFlowLine.paragraph.getAbsoluteStart() + paraSelectionIdx;
+					if (endIdx >= textFlow.textLength)
+					{
+						endIdx = textFlow.textLength - 1;
+					}
+				}
+			} else {
+				endIdx = textFlow.textLength - 1;
+			}
+				
+			if (!extendSelection)
+				begIdx = endIdx;
+											
+			if (begIdx == endIdx)
+			{
+				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);			
+		}
+		  
+		/**
+		 * Sets the TextRange up one line.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 
+		static public function previousLine(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+			
+			if (adjustForOversetBack(range))
+				return true;
+				
+			var textFlow:TextFlow = range.textFlow;
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var isRTLDirection:Boolean = (textFlow.computedFormat.direction == Direction.RTL);			
+
+			if (curLine > 0)	//create, expand or shrink the selection
+			{
+				var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
+				var lineStart:int = curTextFlowLine.absoluteStart;
+				var lineDelta:int = endIdx - lineStart;
+				var currentTextLine:TextLine = curTextFlowLine.getTextLine(true);
+				var para:ParagraphElement = curTextFlowLine.paragraph;
+				var atomIndex:int = currentTextLine.getAtomIndexAtCharIndex(endIdx - para.getAbsoluteStart());
+				var bidiRightToLeft:Boolean = ((currentTextLine.getAtomBidiLevel(atomIndex) % 2) != 0); 				
+				var curPosRect:Rectangle = currentTextLine.getAtomBounds(atomIndex);
+				var currentTextLineX:Number = currentTextLine.x;
+				var curPosRectLeft:Number = curPosRect.left;
+				var curPosRectRight:Number = curPosRect.right;
+				if(textFlow.computedFormat.blockProgression == BlockProgression.RL)
+				{
+					currentTextLineX = currentTextLine.y;
+					curPosRectLeft = curPosRect.top;
+					curPosRectRight = curPosRect.bottom;
+				}
+				
+				//find the atom
+				var globalPoint:Point = new Point();				
+						
+				if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+				{
+					if (!isRTLDirection)
+						globalPoint.x = curPosRect.left;
+					else
+						globalPoint.x = curPosRect.right;
+					globalPoint.y = 0;
+				} else {						
+					globalPoint.x = 0;
+					if (!isRTLDirection)
+						globalPoint.y = curPosRect.top;
+					else
+						globalPoint.y = curPosRect.bottom;
+				}
+				
+				globalPoint = currentTextLine.localToGlobal(globalPoint);
+				
+				//at this point, we have the global point of our current position.  Now adjust x or y to the
+				//baseline of the next line.
+				var prevFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine - 1);
+				// get the last container so that we can make sure the previous line is in view.
+				var controller:ContainerController = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
+				var firstPosInContainer:int = controller.absoluteStart;
+				var lastPosInContainer:int = firstPosInContainer + controller.textLength;
+				if ((prevFlowLine.absoluteStart >= firstPosInContainer) && (prevFlowLine.absoluteStart < lastPosInContainer))
+				{
+					controller.scrollToRange(prevFlowLine.absoluteStart,prevFlowLine.absoluteStart+prevFlowLine.textLength-1);
+				}
+				
+				var preventextLine:TextLine = prevFlowLine.getTextLine(true);
+				if (prevFlowLine.controller == curTextFlowLine.controller)
+				{
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+					{
+						globalPoint.y -= (currentTextLine.y - preventextLine.y);
+					} else {
+						globalPoint.x += (preventextLine.x - currentTextLine.x);
+					}
+				} else {
+					var firstAtomRect:Rectangle = preventextLine.getAtomBounds(0);
+					var firstAtomPoint:Point = new Point();
+					firstAtomPoint.x = firstAtomRect.left;
+					firstAtomPoint.y = 0;
+					firstAtomPoint = preventextLine.localToGlobal(firstAtomPoint);
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL)
+					{
+						globalPoint.x -= curTextFlowLine.controller.container.x;
+						globalPoint.y = firstAtomPoint.y;
+					} else {
+						globalPoint.x = firstAtomPoint.x;
+						globalPoint.y -= curTextFlowLine.controller.container.y; 
+					}					
+				} 
+				
+				atomIndex = preventextLine.getAtomIndexAtPoint(globalPoint.x,globalPoint.y);
+				if (atomIndex == -1)
+				{
+					if(textFlow.computedFormat.blockProgression != BlockProgression.RL) {
+						if (!bidiRightToLeft)
+							endIdx = (globalPoint.x <= preventextLine.x) ? prevFlowLine.absoluteStart : (prevFlowLine.absoluteStart + prevFlowLine.textLength - 1);
+						else
+							endIdx = (globalPoint.x <= preventextLine.x) ? (prevFlowLine.absoluteStart + prevFlowLine.textLength - 1) : prevFlowLine.absoluteStart;						
+					} else {
+						if (!bidiRightToLeft)
+							endIdx = (globalPoint.y <= preventextLine.y) ? prevFlowLine.absoluteStart : (prevFlowLine.absoluteStart + prevFlowLine.textLength - 1);
+						else
+							endIdx = (globalPoint.y <= preventextLine.y)  ? (prevFlowLine.absoluteStart + prevFlowLine.textLength - 1) : prevFlowLine.absoluteStart;						
+					}
+				} else {
+					// get the character box and if check we are past the middle select past this character. 
+					var glyphRect:Rectangle = preventextLine.getAtomBounds(atomIndex);
+					var leanRight:Boolean = false;
+					if(glyphRect)
+					{	
+						//if this is TTB and NOT TCY determine lean based on Y coordinates...
+						var glyphGlobalPoint:Point = new Point();
+						glyphGlobalPoint.x = glyphRect.x;
+						glyphGlobalPoint.y = glyphRect.y;
+						glyphGlobalPoint = preventextLine.localToGlobal(glyphGlobalPoint);
+						
+						if((textFlow.computedFormat.blockProgression == BlockProgression.RL) && preventextLine.getAtomTextRotation(atomIndex) != TextRotation.ROTATE_0)
+							leanRight = (globalPoint.y > (glyphGlobalPoint.y + glyphRect.height/2));
+						else //use X..
+							leanRight = (globalPoint.x > (glyphGlobalPoint.x + glyphRect.width/2));
+					}
+			
+					var paraSelectionIdx:int;
+					if ((preventextLine.getAtomBidiLevel(atomIndex) % 2) != 0) // Right to left case, right is "start" unicode
+						paraSelectionIdx = leanRight ? preventextLine.getAtomTextBlockBeginIndex(atomIndex) : preventextLine.getAtomTextBlockEndIndex(atomIndex);
+					else  {// Left to right case, right is "end" unicode
+						if (isRTLDirection) {
+							if ((leanRight == false) && (atomIndex > 0))
+							{
+								paraSelectionIdx = preventextLine.getAtomTextBlockBeginIndex(atomIndex - 1);	
+							} else {
+								paraSelectionIdx = preventextLine.getAtomTextBlockBeginIndex(atomIndex);
+							}
+						} else {
+							paraSelectionIdx = leanRight ? preventextLine.getAtomTextBlockEndIndex(atomIndex) : preventextLine.getAtomTextBlockBeginIndex(atomIndex);							
+						}
+					}
+					endIdx = prevFlowLine.paragraph.getAbsoluteStart() + paraSelectionIdx;
+				}
+			} else {
+				endIdx = 0;
+			}
+				
+			if (!extendSelection)
+				begIdx = endIdx;
+											
+			if (begIdx == endIdx)
+			{
+				begIdx = updateStartIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateEndIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);			
+		}
+		 
+		/**
+		 * Sets the TextRange down one page.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 
+		static public function nextPage(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			var controller:ContainerController;
+			
+			if (!validateTextRange(range))
+				return false;
+				
+			var textFlow:TextFlow = range.textFlow;
+			
+			// if not the last container go to the beginning of the next container
+			var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(range.activePosition);
+			if (controllerIndex != textFlow.flowComposer.numControllers-1)
+			{
+				range.activePosition = textFlow.flowComposer.getControllerAt(controllerIndex+1).absoluteStart;
+				if (!extendSelection)
+					range.anchorPosition = range.activePosition;
+				return true;
+			}
+			
+			if (!isScrollable(textFlow, range.activePosition))		// paging applies only to containers that scroll
+				return false;
+								
+			if (adjustForOversetForward(range))
+				return true;
+		 	
+			var begIdx:int = range.absoluteStart;
+			var endIdx:int = range.absoluteEnd;
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
+			
+			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
+			var linePos:int = endIdx - lineStart;
+ 			var nextLine:int;
+ 			var nextTextFlowLine:TextFlowLine = curTextFlowLine;
+ 											
+			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
+			var amount:Number;
+			
+			// get the last container
+			controller = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
+
+			if (isTTB)
+			{
+				amount = controller.compositionWidth * textFlow.configuration.scrollPagePercentage;
+			} else {
+				amount = controller.compositionHeight * textFlow.configuration.scrollPagePercentage;
+			}
+  								
+ 			if (isTTB)
+ 			{
+ 				if ((controller.horizontalScrollPosition - amount) < -controller.contentWidth)
+ 				{
+ 					controller.horizontalScrollPosition = -controller.contentWidth;
+					nextLine = textFlow.flowComposer.numLines - 1;
+					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								
+ 				} else
+ 				{
+ 					var oldHorzScrollPos:Number = controller.horizontalScrollPosition;
+ 					controller.horizontalScrollPosition -= amount;
+ 					var newHorzScrollPos:Number = controller.horizontalScrollPosition;
+ 					if (oldHorzScrollPos == newHorzScrollPos) {
+						nextLine = textFlow.flowComposer.numLines - 1;
+						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);													
+ 					} else {
+ 						nextLine = curLine;
+ 						while (nextLine < (textFlow.flowComposer.numLines - 1))
+ 						{
+ 							nextLine++;
+							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
+							if ((curTextFlowLine.x - nextTextFlowLine.x) >= (oldHorzScrollPos - newHorzScrollPos))
+								break;
+ 						}
+ 					}
+ 				} 					
+ 			}
+ 			else
+ 			{
+ 				if ((controller.verticalScrollPosition + amount) > controller.contentHeight)
+ 				{
+ 					controller.verticalScrollPosition = controller.contentHeight;
+					nextLine = textFlow.flowComposer.numLines - 1;
+					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 						
+ 				} else
+ 				{
+ 					var oldVertScrollPos:Number = controller.verticalScrollPosition;
+ 					controller.verticalScrollPosition += amount;
+ 					var newVertScrollPos:Number = controller.verticalScrollPosition;
+ 					if (newVertScrollPos == oldVertScrollPos) {
+						nextLine = textFlow.flowComposer.numLines - 1;
+						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 											
+ 					} else {
+ 						nextLine = curLine;
+ 						while (nextLine < (textFlow.flowComposer.numLines - 1))
+ 						{
+ 							nextLine++;
+							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
+							if ((nextTextFlowLine.y - curTextFlowLine.y) >= (newVertScrollPos - oldVertScrollPos))
+								break;
+ 						} 						
+ 					}
+ 				}
+ 			}
+ 			
+ 			endIdx = nextTextFlowLine.absoluteStart + linePos; 
+			var nextLineEnd:int = nextTextFlowLine.absoluteStart + nextTextFlowLine.textLength - 1;
+			if (endIdx > nextLineEnd)
+			{
+				endIdx = nextLineEnd;
+			}
+			
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			}
+			
+			return range.updateRange(begIdx,endIdx);				
+		 }
+		  
+		/**
+		 * Sets the TextRange up one page.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 
+		static public function previousPage(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+				
+			var textFlow:TextFlow = range.textFlow;
+			
+			var controllerIndex:int = textFlow.flowComposer.findControllerIndexAtPosition(range.activePosition);
+			var controller:ContainerController = textFlow.flowComposer.getControllerAt(controllerIndex);
+			
+			// first line in container
+			var controllerFirstLine:TextFlowLine = textFlow.flowComposer.findLineAtPosition(controller.absoluteStart);
+
+			// if on the first line of a controller go to the beginning of the previous controller
+			if (range.activePosition <= controller.absoluteStart+controllerFirstLine.textLength)
+			{
+				if (controllerIndex == 0)
+					return false;
+				range.activePosition = textFlow.flowComposer.getControllerAt(controllerIndex-1).absoluteStart;
+				if (!extendSelection)
+					range.anchorPosition = range.activePosition;
+				return true;
+			}
+			
+			// if not the last container go to the beginning of the current container
+			if (controllerIndex != textFlow.flowComposer.numControllers-1)
+			{
+				range.activePosition = controller.absoluteStart;
+				if (!extendSelection)
+					range.anchorPosition = range.activePosition;
+				return true;
+			}
+				
+			if (!isScrollable(textFlow, range.activePosition))		// paging applies only to containers that scroll
+				return false;
+								
+			if (adjustForOversetBack(range))
+				return true;
+			
+			var begIdx:int = range.absoluteStart;
+			var endIdx:int = range.absoluteEnd;
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var curTextFlowLine:TextFlowLine = textFlow.flowComposer.getLineAt(curLine);
+			
+			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
+			var linePos:int = endIdx - lineStart;
+ 			var nextLine:int;
+ 			var nextLinePos:int;
+ 			var nextTextFlowLine:TextFlowLine = curTextFlowLine;
+ 											
+			var isTTB:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
+			var amount:Number;
+			
+			// get the last container
+			controller = textFlow.flowComposer.getControllerAt(textFlow.flowComposer.numControllers-1);
+			
+			if (isTTB)
+			{
+				amount = controller.compositionWidth * textFlow.configuration.scrollPagePercentage;
+			} else {
+				amount = controller.compositionHeight * textFlow.configuration.scrollPagePercentage;
+			}
+  								
+ 			if (isTTB)
+ 			{
+ 				if ((controller.horizontalScrollPosition + amount + controller.compositionWidth) > 0)
+ 				{
+ 					controller.horizontalScrollPosition = 0;
+					nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
+					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								
+ 				} else
+ 				{
+ 					var oldHorzPos:Number = controller.horizontalScrollPosition;
+ 					controller.horizontalScrollPosition += amount;
+ 					var newHorzPos:Number = controller.horizontalScrollPosition;
+ 					if (oldHorzPos == newHorzPos) {
+						nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
+						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);													
+ 					} else {
+ 						nextLine = curLine;
+ 						while (nextLine > 0)
+ 						{
+ 							nextLine--;
+							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
+							if ((nextTextFlowLine.x - curTextFlowLine.x) >= (newHorzPos - oldHorzPos) || nextTextFlowLine.absoluteStart < controller.absoluteStart)
+								break;
+ 						}
+ 					}
+ 				} 					
+ 			}
+ 			else
+ 			{
+ 				if ((controller.verticalScrollPosition - amount + controller.compositionHeight) < 0)
+ 				{
+ 					controller.verticalScrollPosition = 0;
+					nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
+					nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 						
+ 				} else
+ 				{
+ 					var oldVertPos:Number = controller.verticalScrollPosition;
+ 					controller.verticalScrollPosition -= amount;
+ 					var newVertPos:Number = controller.verticalScrollPosition;
+ 					if (oldVertPos == newVertPos) {
+						nextLine = textFlow.flowComposer.findLineIndexAtPosition(controller.absoluteStart);
+						nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);								 											
+ 					} else {
+ 						nextLine = curLine;
+ 						while (nextLine > 0)
+ 						{
+ 							nextLine--;
+							nextTextFlowLine = textFlow.flowComposer.getLineAt(nextLine);
+							if ((curTextFlowLine.y - nextTextFlowLine.y) >= (oldVertPos - newVertPos) || nextTextFlowLine.absoluteStart < controller.absoluteStart)
+								break;
+ 						}
+ 					} 						
+ 				}
+ 			}
+ 			
+ 			endIdx = nextTextFlowLine.absoluteStart + linePos; 
+			var nextLineEnd:int = nextTextFlowLine.absoluteStart + nextTextFlowLine.textLength - 1;
+			if (endIdx > nextLineEnd)
+			{
+				endIdx = nextLineEnd;
+			}
+			
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);						
+		} 
+		/**
+		 * Sets the TextRange at the end of the line.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 
+		static public function endOfLine(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+			
+
+			var textFlow:TextFlow = range.textFlow;
+			checkCompose(textFlow.flowComposer, range.absoluteEnd);
+
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
+			var lineEnd:int = lineStart + textFlow.flowComposer.getLineAt(curLine).textLength - 1;
+			
+			var leaf:FlowLeafElement = textFlow.findLeaf(endIdx);
+			var para:ParagraphElement = leaf.getParagraph();
+			if (CharacterUtil.isWhitespace(para.getCharCodeAtPosition(lineEnd - para.getAbsoluteStart())))
+			{
+				endIdx = lineEnd;
+			} else {
+				endIdx = lineEnd + 1;
+			}
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);
+		 }
+		 
+		/**
+		 * Sets the TextRange at the beginning of the line.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 		 
+		static public function startOfLine(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+				
+			var textFlow:TextFlow = range.textFlow;
+			checkCompose(textFlow.flowComposer, range.absoluteEnd);
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+		
+			var curLine:int = textFlow.flowComposer.findLineIndexAtPosition(endIdx);
+			var lineStart:int = textFlow.flowComposer.getLineAt(curLine).absoluteStart;
+			endIdx = lineStart;
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);
+		} 
+		/**
+		 * Sets the TextRange at the end of the document.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 		 		 
+		static public function endOfDocument(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+				
+			var textFlow:TextFlow = range.textFlow
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			endIdx = textFlow.textLength - 1;
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);				
+		}
+		
+		/**
+		 * Sets the TextRange at the beginning of the document.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 		 		 		 
+		static public function startOfDocument(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = 0;
+
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateEndIfInReadOnlyElement(range.textFlow, begIdx);
+				endIdx = updateStartIfInReadOnlyElement(range.textFlow, endIdx);
+			} else {
+				endIdx = updateStartIfInReadOnlyElement(range.textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);				
+		}
+		 
+		/**
+		 * Sets the TextRange at the beginning of the paragraph.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 		 		 		 		 
+		static public function startOfParagraph(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			var leaf:FlowLeafElement = range.textFlow.findLeaf(endIdx);
+			var para:ParagraphElement = leaf.getParagraph();
+			
+			endIdx = para.getAbsoluteStart();
+			if (!extendSelection)
+				begIdx = endIdx;							
+
+			if (begIdx == endIdx)
+			{
+				begIdx = updateStartIfInReadOnlyElement(range.textFlow, begIdx);
+				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
+			} else {
+				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);
+		 }
+		 
+		/**
+		 * Sets the TextRange at the end of the paragraph.
+		 * @param extendSelection	Indicates that only activeIndex should move
+		 * @return true if selection changed.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */		 		 		 		 		 		 		 		 		 		 		 		 		 		 
+		static public function endOfParagraph(range:TextRange, extendSelection:Boolean = false):Boolean
+		{
+			if (!validateTextRange(range))
+				return false;
+				
+			var begIdx:int = range.anchorPosition;
+			var endIdx:int = range.activePosition;
+			var leaf:FlowLeafElement = range.textFlow.findLeaf(endIdx);
+			var para:ParagraphElement = leaf.getParagraph();
+			
+			endIdx = para.getAbsoluteStart() + para.textLength - 1;
+			if (!extendSelection)
+				begIdx = endIdx;							
+			if (begIdx == endIdx)
+			{
+				begIdx = updateStartIfInReadOnlyElement(range.textFlow, begIdx);
+				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
+			} else {
+				endIdx = updateEndIfInReadOnlyElement(range.textFlow, endIdx);
+			}
+			return range.updateRange(begIdx,endIdx);
+		 }
+	
+		/** If the range is in overset text (after the last container in a non-scrolling flow), adjust the range so it is at the end of the flow. */
+		static private function adjustForOversetForward(range:TextRange):Boolean
+		{
+			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
+			var controller:ContainerController = null;
+			checkCompose(flowComposer, range.absoluteEnd);
+			if (flowComposer && flowComposer.numControllers)
+			{
+				var controllerIndex:int = flowComposer.findControllerIndexAtPosition(range.absoluteEnd);
+				if (controllerIndex >= 0)
+					controller = flowComposer.getControllerAt(controllerIndex);
+				if (controllerIndex == flowComposer.numControllers-1)
+				{
+					if (controller.absoluteStart + controller.textLength <= range.absoluteEnd && controller.absoluteStart + controller.textLength != range.textFlow.textLength)
+						controller = null;
+				}
+			}
+
+			if (!controller)		// we're overset, or one position before overset
+			{
+				range.anchorPosition = range.textFlow.textLength - 1;
+				range.activePosition = range.anchorPosition;
+				return true;
+			}
+			return false;
+		}
+		
+		/** If the range is in overset text (after the last container in a non-scrolling flow), adjust the range so it is at the end of the last controller in the flow. */
+		static private function adjustForOversetBack(range:TextRange):Boolean
+		{
+			var flowComposer:IFlowComposer = range.textFlow.flowComposer;
+			if (flowComposer)
+			{
+				checkCompose(flowComposer, range.absoluteEnd);
+				if (flowComposer.findControllerIndexAtPosition(range.absoluteEnd) == -1)
+				{
+					range.anchorPosition = endOfLastController(range.textFlow);
+					range.activePosition = range.anchorPosition;
+					return true;
+				}				
+			}
+				
+			return false;
+		}
+		
+		private static function checkCompose(flowComposer:IFlowComposer, pos:int):void
+		{
+			if (flowComposer.damageAbsoluteStart <= pos)
+				flowComposer.composeToPosition(pos);
+		}
+		
+		// Returns absolute position of the last controller in the flow, or 0 if the flow has no controllers
+		private static function endOfLastController(flowRoot:TextFlow):int
+		{
+			var flowComposer:IFlowComposer = flowRoot.flowComposer;
+			if (!flowComposer || flowComposer.numControllers <= 0)
+				return 0;
+				
+			var controller:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1);
+			return controller.absoluteStart + Math.max(controller.textLength - 1, 0);
+		}
+		
+		// Returns true if the position is in the overset text after the last container in the flow.
+		private static function isOverset(flowRoot:TextFlow, absolutePos:int):Boolean
+		{
+			var flowComposer:IFlowComposer = flowRoot.flowComposer;
+			return (!flowComposer || flowComposer.findControllerIndexAtPosition(absolutePos) == -1);
+		}
+	
+		// Returns true if the position is in a scollable container
+		private static function isScrollable(flowRoot:TextFlow, absolutePos:int):Boolean
+		{
+			var flowComposer:IFlowComposer = flowRoot.flowComposer;
+			if (!flowComposer)
+				return false;
+			var controllerIndex:int = flowComposer.findControllerIndexAtPosition(absolutePos);
+			if (controllerIndex >= 0)
+			{
+				var controller:ContainerController = flowComposer.getControllerAt(controllerIndex);
+				var blockProgression:String = controller.rootElement.computedFormat.blockProgression;
+				return ((blockProgression == BlockProgression.TB && controller.verticalScrollPolicy != ScrollPolicy.OFF) ||
+					(blockProgression == BlockProgression.RL && controller.horizontalScrollPolicy != ScrollPolicy.OFF));
+			}
+			return false;
+		}
+		
+	}
+}
diff --git a/textLayout_edit/src/flashx/undo/IOperation.as b/textLayout_edit/src/flashx/undo/IOperation.as
new file mode 100755
index 0000000..c94cb3a
--- /dev/null
+++ b/textLayout_edit/src/flashx/undo/IOperation.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.undo
+{
+	/** 
+	 * IOperation defines the interface for operations that can be undone and redone.
+	 *  
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public interface IOperation
+	{
+		/** 
+		 * Reperforms the operation.
+		 * 
+		 * <p>The operation is also responsible for pushing itself onto the undo stack.</p>
+		 *  
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function performRedo():void;
+		/** 
+		 * Reverses the operation.
+		 * 
+		 * <p>The operation is also responsible for pushing itself onto the redo stack.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+	 	 * @langversion 3.0
+		 */
+		function performUndo():void;
+	}
+}
diff --git a/textLayout_edit/src/flashx/undo/IUndoManager.as b/textLayout_edit/src/flashx/undo/IUndoManager.as
new file mode 100755
index 0000000..0e3ab2d
--- /dev/null
+++ b/textLayout_edit/src/flashx/undo/IUndoManager.as
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.undo
+{	
+	/**
+	 * IUndoManager defines the interface for managing the undo and redo stacks.
+	 * 
+	 * <p>An undo manager maintains a stack of operations that can be undone and redone.</p>
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 */
+	public interface IUndoManager 
+	{	
+		/**
+		 * Clears both the undo and the redo histories.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		function clearAll():void;
+		
+		/**
+		 * The maximum number of undoable or redoable operations to track.
+		 * 
+		 * <p>To disable the undo function, set this value to 0.</p> 
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function get undoAndRedoItemLimit():int;
+		function set undoAndRedoItemLimit(value:int):void;
+
+		/**
+		 * Indicates whether there is currently an operation that can be undone.
+		 * 
+		 * @return Boolean <code>true</code>, if there is an operation on the undo stack that can be reversed.
+		 * Otherwise, <code>false</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function canUndo():Boolean;
+		
+		/**
+		 * Returns the next operation to be undone.
+		 * 
+		 * @return IOperation The undoable IOperation object, or <code>null</code>, if no undoable operation
+		 * is on the stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function peekUndo():IOperation;
+		
+		/**
+		 * Removes the next operation to be undone from the undo stack, and returns it.
+		 * 
+		 * @return IOperation The undoable IOperation object, or <code>null</code>, if no undoable operation
+		 * is on the stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function popUndo():IOperation;
+
+		/**
+		 * Adds an undoable operation to the undo stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function pushUndo(operation:IOperation):void;
+		
+		/**
+		 * Clears the redo stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function clearRedo():void;
+
+		/**
+		 * Indicates whether there is currently an operation that can be redone.
+		 * 
+		 * @return Boolean <code>true</code>, if there is an operation on the redo stack that can be redone.
+		 * Otherwise, <code>false</code>.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function canRedo():Boolean;
+
+		/**
+		 * Returns the next operation to be redone.
+		 * 
+		 * @return IOperation The redoable IOperation object, or <code>null</code>, if no redoable operation
+		 * is on the stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function peekRedo():IOperation;
+		
+		/**
+		 * Removes the next operation to be redone from the redo stack, and returns it.
+		 * 
+		 * @return IOperation The redoable IOperation object, or <code>null</code>, if no redoable operation
+		 * is on the stack.
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function popRedo():IOperation;
+
+		/**
+		 * Adds a redoable operation to the redo stack.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		function pushRedo(operation:IOperation):void;
+
+		/** 
+		 * Removes the next IOperation object from the undo stack and calls the performUndo() 
+		 * function of that object.
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager#undo()
+		 * @see flashx.undo.IUndoManager#canUndo()
+		 * @see flashx.undo.IUndoManager#clearUndo()
+		 * @see flashx.undo.IUndoManager#peekUndo()
+		 * @see flashx.undo.IUndoManager#pushUndo()
+		 * @see flashx.undo.IUndoManager#popUndo()
+		 */
+		function undo():void;
+		
+		/** 
+		 * Removes the next IOperation object from the redo stack and calls the performRedo() 
+		 * function of that object.
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager#redo()
+		 * @see flashx.undo.IUndoManager#canRedo()
+		 * @see flashx.undo.IUndoManager#clearRedo()
+		 * @see flashx.undo.IUndoManager#peekRedo()
+		 * @see flashx.undo.IUndoManager#pushRedo()
+		 * @see flashx.undo.IUndoManager#popRedo()
+		 */
+		function redo():void;						
+	}
+}
diff --git a/textLayout_edit/src/flashx/undo/UndoManager.as b/textLayout_edit/src/flashx/undo/UndoManager.as
new file mode 100755
index 0000000..845d904
--- /dev/null
+++ b/textLayout_edit/src/flashx/undo/UndoManager.as
@@ -0,0 +1,251 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.undo
+{
+			
+	/** 
+	 * The UndoManager class manages the history of editing operations on a text flow so
+	 * that these operations can be undone and redone.
+	 * 
+	 * <p>The undo manager maintains two stacks of IOperation objects. When a reversible
+	 * operation is executed, it is placed on the undo stack. If that operation is undone,
+	 * it is removed from the undo stack, reversed, and placed on the redo stack. Likewise, 
+	 * if that operation is then redone, it is removed from the redo stack, re-executed, and
+	 * then placed onto the undo stack again. If another operation is executed first, the redo 
+	 * stack is cleared.</p>
+	 * 
+	 * <p>If the TextFlow is modified directly (not via
+	 * calls to the edit manager, but directly via calls to the managed FlowElement objects), then the edit manager
+	 * clears the undo stack to prevent the stack from getting out of sync with the current state.</p>
+	 * 
+	 * 
+	 * @playerversion Flash 10
+	 * @playerversion AIR 1.5
+ 	 * @langversion 3.0
+	 *
+	 * @see flashx.textLayout.edit.EditManager
+	 */
+	public class UndoManager implements IUndoManager
+	{
+		private var undoStack:Array;
+		private var redoStack:Array;
+		
+		private var _undoAndRedoItemLimit:int = 25;
+
+		/**
+		 * Creates an UndoManager object.
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function UndoManager()
+		{
+			undoStack = new Array();
+			redoStack = new Array();
+		}
+		
+		/**
+		 * @copy IUndoManager#clearAll()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */	
+		public function clearAll():void
+		{
+			undoStack.length = 0;
+			redoStack.length = 0;			
+		}
+		
+		/**
+		 * @copy IUndoManager#canUndo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function canUndo():Boolean
+		{
+			return undoStack.length > 0;
+		}
+		
+		/**
+		 * @copy IUndoManager#peekUndo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function peekUndo():IOperation
+		{
+			return undoStack.length > 0 ? undoStack[undoStack.length-1] : null;
+		}
+		
+		/**
+		 * @copy IUndoManager#popUndo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function popUndo():IOperation
+		{
+			return IOperation(undoStack.pop());
+		}
+
+		/**
+		 * @copy IUndoManager#pushUndo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function pushUndo(operation:IOperation):void
+		{
+			undoStack.push(operation);
+			trimUndoRedoStacks();
+		}
+		
+		/**
+		 * @copy IUndoManager#canRedo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function canRedo():Boolean
+		{
+			return redoStack.length > 0;
+		}
+
+		/**
+		 * @copy IUndoManager#clearRedo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function clearRedo():void
+		{
+			redoStack.length = 0;
+		}
+
+		/**
+		 * @copy IUndoManager#peekRedo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function peekRedo():IOperation
+		{
+			return redoStack.length > 0 ? redoStack[redoStack.length-1] : null;
+		}
+		
+		/**
+		 * @copy IUndoManager#popRedo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function popRedo():IOperation
+		{
+			return IOperation(redoStack.pop());
+		}
+
+		/**
+		 * @copy IUndoManager#pushRedo()
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function pushRedo(operation:IOperation):void
+		{
+			redoStack.push(operation);
+			trimUndoRedoStacks();
+		}
+
+		/**
+		 * @copy IUndoManager#undoAndRedoItemLimit
+		 * @tiptext The maximum number of undoable or redoable operations to track. 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function get undoAndRedoItemLimit():int
+		{ return _undoAndRedoItemLimit; }
+		public function set undoAndRedoItemLimit(value:int):void
+		{ 
+			_undoAndRedoItemLimit = value;
+			trimUndoRedoStacks();
+		}
+
+		/** 
+		 * @copy IUndoManager#undo()
+		 * @see flashx.textLayout.edit.IEditManager#undo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function undo():void
+		{
+			if (canUndo())
+			{
+				var undoOp:IOperation = popUndo();
+				undoOp.performUndo();
+			}
+		}
+		
+		/** 
+		 * @copy IUndoManager#redo()
+		 * 
+		 * @see flashx.textLayout.edit.IEditManager#redo()
+		 * 
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+ 	 	 * @langversion 3.0
+		 */
+		public function redo():void
+		{
+			if (canRedo())
+			{
+				var redoOp:IOperation = popRedo();
+				redoOp.performRedo();
+			}			
+		}									
+		
+		/** trim the sizes of the undo/redo stacks to the maximum limits */
+		private function trimUndoRedoStacks():void
+		{
+			// trim the undoStack and the redoStack so its in bounds 
+			var numItems:int = undoStack.length + redoStack.length;
+			if (numItems > _undoAndRedoItemLimit)
+			{
+				// trim redoStack first
+				var numToSplice:int = Math.min(numItems-_undoAndRedoItemLimit,redoStack.length);
+				if (numToSplice)
+				{
+					redoStack.splice(0,numToSplice);
+					numItems = undoStack.length+redoStack.length;
+				} 
+				// trim some undoable items
+				if (numItems > _undoAndRedoItemLimit)
+				{
+					numToSplice = Math.min(numItems-_undoAndRedoItemLimit,undoStack.length);
+					undoStack.splice(0,numToSplice);
+				}
+			}
+		}
+		
+	}
+}
diff --git a/textLayout_layout/.actionScriptProperties b/textLayout_layout/.actionScriptProperties
new file mode 100755
index 0000000..375eb43
--- /dev/null
+++ b/textLayout_layout/.actionScriptProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<actionScriptProperties mainApplicationPath="textLayout_layout.as" projectUUID="f693cc15-9fd2-48a8-a0bd-ce309dda5fa0" version="6">
+  <compiler additionalCompilerArguments="-locale en_US -load-config+=../../config.xml" autoRSLOrdering="true" copyDependentFiles="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="false" htmlHistoryManagement="false" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
+    <compilerSourcePath/>
+    <libraryPath defaultLinkType="0">
+      <libraryPathEntry kind="3" linkType="4" path="/textLayout_conversion/bin/textLayout_conversion.swc" useDefaultLinkType="true"/>
+      <libraryPathEntry kind="3" linkType="4" path="/textLayout_core/bin/textLayout_core.swc" useDefaultLinkType="true"/>
+      <libraryPathEntry kind="4" path="">
+        <excludedEntries>
+          <libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flex.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="4" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/rpc_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="rpc_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="2" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/framework_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="framework_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
+          <libraryPathEntry index="1" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/textLayout.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/textLayout_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="textLayout_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry index="3" kind="3" linkType="4" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="true">
+            <crossDomainRsls>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="http://fpdownload.adobe.com/pub/swz/crossdomain.xml" rslUrl="http://fpdownload.adobe.com/pub/swz/flex/4.0.0.10485/spark_4.0.0.10485.swz"/>
+              <crossDomainRslEntry autoExtract="true" policyFileUrl="" rslUrl="spark_4.0.0.10485.swz"/>
+            </crossDomainRsls>
+          </libraryPathEntry>
+          <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/utilities.swc" useDefaultLinkType="false"/>
+        </excludedEntries>
+      </libraryPathEntry>
+    </libraryPath>
+    <sourceAttachmentPath/>
+  </compiler>
+  <applications>
+    <application path="textLayout_layout.as"/>
+  </applications>
+  <modules/>
+  <buildCSSFiles/>
+</actionScriptProperties>
diff --git a/textLayout_layout/.flexLibProperties b/textLayout_layout/.flexLibProperties
new file mode 100755
index 0000000..1439998
--- /dev/null
+++ b/textLayout_layout/.flexLibProperties
@@ -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.
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<flexLibProperties includeAllClasses="false" version="3">
+  <includeClasses>
+    <classEntry path="flashx.textLayout.LayoutClasses"/>
+  </includeClasses>
+  <includeResources/>
+  <namespaceManifests/>
+</flexLibProperties>
diff --git a/textLayout_layout/.project b/textLayout_layout/.project
new file mode 100755
index 0000000..213b3c8
--- /dev/null
+++ b/textLayout_layout/.project
@@ -0,0 +1,36 @@
+<?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.
+-->
+<projectDescription>
+	<name>textLayout_layout</name>
+	<comment></comment>
+	<projects>
+		<project>textLayout_conversion</project>
+		<project>textLayout_core</project>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.adobe.flexbuilder.project.flexbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.adobe.flexbuilder.project.flexlibnature</nature>
+		<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
+	</natures>
+</projectDescription>
diff --git a/textLayout_layout/src/flashx/textLayout/BuildInfoLayout.as b/textLayout_layout/src/flashx/textLayout/BuildInfoLayout.as
new file mode 100755
index 0000000..18f508a
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/BuildInfoLayout.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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout
+{
+	/**
+	 * Contains identifying information for the current build. 
+	 * This may not be the form that this information is presented in the final API.
+	 */
+	public class BuildInfoLayout
+	{		
+		[ExcludeClass]
+		/**
+		 * Contains the current version number. 
+		 */
+		public static const VERSION:String = "1.0";
+		
+		/**
+		 * Contains the current build number. 
+		 * It is static and can be called with <code>BuildInfo.kBuildNumber</code>
+		 * <p>String Format: "BuildNumber (Changelist)"</p>
+		 */
+		public static const kBuildNumber:String = "595 (738907)";
+		
+		/**
+		 * Contains the branch name. 
+		 */
+		public static const kBranch:String = "1.0";
+
+		/**
+		 * @private 
+		 */
+		public static const AUDIT_ID:String = "";
+		
+		/**
+		 * @private 
+		 */
+		public function dontStripAuditID():String
+		{
+			return AUDIT_ID;
+		}
+	}
+}
+
diff --git a/textLayout_layout/src/flashx/textLayout/LayoutClasses.as b/textLayout_layout/src/flashx/textLayout/LayoutClasses.as
new file mode 100755
index 0000000..6dcb20c
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/LayoutClasses.as
@@ -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.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flashx.textLayout
+{
+	internal class LayoutClasses
+	{
+		import flashx.textLayout.BuildInfoLayout; BuildInfoLayout;
+		
+		import flashx.textLayout.compose.LayoutFlowComposer; LayoutFlowComposer;
+		import flashx.textLayout.container.LayoutContainerController; LayoutContainerController;
+		import flashx.textLayout.container.IWrapManager; IWrapManager;
+		import flashx.textLayout.container.WrapManager; WrapManager;
+		
+		import flashx.textLayout.conversion.LayoutConfiguration; LayoutConfiguration;
+	}
+}
+
diff --git a/textLayout_layout/src/flashx/textLayout/compose/LayoutComposeState.as b/textLayout_layout/src/flashx/textLayout/compose/LayoutComposeState.as
new file mode 100755
index 0000000..a55ef76
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/compose/LayoutComposeState.as
@@ -0,0 +1,269 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.display.Graphics;
+	import flash.display.Sprite;
+	import flash.geom.Rectangle;
+	import flash.text.engine.TextBaseline;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.IFloatController;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.FlowElement;
+	import flashx.textLayout.elements.FlowGroupElement;
+	import flashx.textLayout.elements.FlowLeafElement;
+	import flashx.textLayout.elements.InlineGraphicElement;
+	import flashx.textLayout.elements.InlineGraphicElementStatus;
+	import flashx.textLayout.elements.ParagraphElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.formats.BlockProgression;
+	import flashx.textLayout.formats.Float;
+	import flashx.textLayout.tlf_internal;
+		
+	use namespace tlf_internal;
+	
+	/** Keeps track of internal state during composition. 
+	 * 
+	 * This is the advanced layout version, used when there are floats, wraps, or columns.
+	 */
+	public class LayoutComposeState extends ComposeState 
+	{
+		// a single ComposeState that is checked out and checked in
+		static private var _sharedLayoutComposeState:LayoutComposeState;
+
+		/** @private */
+		static tlf_internal function getLayoutComposeState():LayoutComposeState
+		{
+			var rslt:LayoutComposeState = _sharedLayoutComposeState ? _sharedLayoutComposeState : new LayoutComposeState();
+			_sharedLayoutComposeState = null;
+			return rslt;
+		}
+		
+		/** @private */
+		static tlf_internal function releaseLayoutComposeState(state:ComposeState):void
+		{
+			if (_sharedLayoutComposeState == null)
+				_sharedLayoutComposeState = state as LayoutComposeState;
+		}
+		
+		public function LayoutComposeState()
+		{
+			super();
+		}
+		/** @private */
+		protected override function createParcelList():IParcelList
+		{
+			return LayoutParcelList.getLayoutParcelList();
+
+		}
+		/** @private */
+		protected override function releaseParcelList(list:IParcelList):void
+		{
+			LayoutParcelList.releaseLayoutParcelList(list);
+		}
+		
+		// Debugging code to show parcel edges - requires removing graphics.clear from ContainerControllerBase
+	/*	CONFIG::debug override public function composeTextFlow(textFlow:TextFlow):int
+		{
+			var value:int = super.composeTextFlow(textFlow);
+			var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
+			if (controller)
+			{
+				var container:Sprite = textFlow.flowComposer.getControllerAt(0).container as Sprite;
+				var graphics:Graphics = container.graphics;
+				graphics.clear();
+				graphics.lineStyle(1, 0xFF0000);
+				var boundsArray:Array = LayoutParcelList(_parcelList).getBounds();
+				for (var i:int = 0; i < boundsArray.length; ++i)
+				{
+					var bounds:Rectangle = boundsArray[i] as Rectangle;
+					graphics.moveTo(bounds.x, bounds.y);
+					graphics.lineTo(bounds.right, bounds.y);
+					graphics.lineTo(bounds.right, bounds.bottom);
+					graphics.lineTo(bounds.left, bounds.bottom);
+					graphics.lineTo(bounds.left, bounds.top);
+				}
+			}
+			
+			return value;
+		} */
+		
+		/* @private */
+		override protected function parcelHasChanged(newParcel:Parcel):void
+		{
+			if (_curParcel && newParcel && _curParcel.controller == newParcel.controller && _curParcel.column == newParcel.column)
+				vjDisableThisParcel = true;
+			super.parcelHasChanged(newParcel);
+		}
+		
+		/* @private */
+		protected override function composeFloat(elem:ContainerFormattedElement,composeFrame:ContainerController):void
+		{
+			elem.createGeometry(null);
+			// TODO: support arbitrary containers?
+			var floatContainer:DisplayObjectContainer = ContainerFormattedElement(elem).flowComposer.getControllerAt(0).container as DisplayObjectContainer;
+			// var floatContainer:DisplayObjectContainer = ContainerFormattedElement(elem).container as DisplayObjectContainer;
+			if (floatContainer != null) // is inline
+			{
+				if (!(composeFrame is IFloatController))
+					throw("need a float layout-capable controller!");
+				// Add as an inline, figure out the size of the inline, wrap around the inline
+				var parcelRect:Rectangle = IFloatController(composeFrame).computeInlineArea(floatContainer);
+
+				// See if it fits. If so, update the state to show the change. If not, remove the item.
+				if (parcelList.createParcel(parcelRect, elem.computedFormat.blockProgression, true /* next text goes below */))
+				{
+					floatContainer.x = parcelList.left;
+					floatContainer.y = parcelList.top;
+					floatContainer.height = parcelRect.height;
+					IFloatController(parcelList.controller).recordInlineChild(floatContainer);
+
+					//_contentAlignmentWidth = Math.max(_contentAlignmentWidth, parcelList.right);
+					parcelList.addTotalDepth(parcelRect.height);
+					parcelList.next();		 // advance to next parcel
+				}
+			}
+			
+			_curLineIndex = composeFrame.rootElement.getTextFlow().flowComposer.findLineIndexAtPosition(elem.getAbsoluteStart() + elem.textLength);
+			vjDisableThisParcel = true;
+			vjBeginLineIndex = _curLineIndex;
+		}
+
+		/*
+		 * Compose a floating graphic
+		 * 
+		 * @param elem	float we'e composing
+		 */
+		protected function composeFloatInline(elem:InlineGraphicElement):void
+		{
+			if (elem.elementHeight == 0 || elem.elementWidth == 0)		// can't compose yet -- graphic isn't ready
+				return;
+			
+			var containerElement:ContainerFormattedElement = elem.getAncestorWithContainer();
+			var blockProgression:String = containerElement.computedFormat.blockProgression;
+			
+		// HACK!!!
+		//	if the baselineZero is set to ideographicTop, then the descent is the point size (measured from ideographic top)
+		//	but in this case we've already factored that into the line height, so we're adding twice. Very confusing.
+			var effectiveLastLineDescent:Number = 0;
+			if (!isNaN(_lastLineDescent))
+				effectiveLastLineDescent = _lastLineDescent;
+			
+			var floatRect:Rectangle = new Rectangle(parcelList.left, parcelList.top, elem.elementWidth, elem.elementHeight);
+			if (blockProgression == BlockProgression.RL)
+			{				
+				floatRect.left -= effectiveLastLineDescent;
+				if (elem.float == Float.RIGHT)
+					floatRect.offset(0, (parcelList.bottom - elem.elementHeight) - floatRect.y);
+			}
+			else
+			{				
+				floatRect.bottom += effectiveLastLineDescent;
+				if (elem.float == Float.RIGHT)
+					floatRect.offset((parcelList.right - elem.elementWidth) - floatRect.x, 0);
+			}
+				
+			// See if it fits. If so, update the state to show the change. If not, remove the item.
+			if (parcelList.createParcelExperimental(floatRect, elem.float == Float.RIGHT ? "left" : "right"))
+			{
+				var graphic:DisplayObject = elem.graphic;
+				if (graphic)
+				{
+					IFloatController(parcelList.controller).recordInlineChild(graphic);
+					graphic.x = parcelList.left;
+					graphic.y = parcelList.top;
+					if (blockProgression == BlockProgression.TB)
+						graphic.y += effectiveLastLineDescent;
+				}
+
+				if (blockProgression == BlockProgression.TB)
+				{
+					parcelList.addTotalDepth(floatRect.height);
+					//_contentAlignmentWidth = Math.max(_contentAlignmentWidth, floatRect.width);
+					
+				}
+				else
+				{
+					parcelList.addTotalDepth(floatRect.width);
+					//_contentAlignmentWidth = Math.max(_contentAlignmentWidth, floatRect.height);					
+				}
+				parcelList.next();		 // advance to next parcel
+			}
+			
+		//	_curLineIndex = _curParcel.controller.rootElement.getTextFlow().getAbsoluteLineIndex(elem.getAbsoluteStart() + elem.textLength);
+			vjDisableThisParcel = true;
+		//	vjBeginLineIndex = _curLineIndex;
+		}
+		
+		// Called from composeParagraphElement when we are starting to compose a line. Has hooks to handle floats.
+		protected override function startLine():void
+		{
+			// Compose floats that appear at the start of the line, before processing any text. That way the following text will
+			// wrap correctly
+			if (_curElement is InlineGraphicElement && InlineGraphicElement(_curElement).float != Float.NONE)
+			{
+				var graphic:InlineGraphicElement = InlineGraphicElement(_curElement);
+				while (graphic && graphic.float != Float.NONE)
+				{
+					composeFloatInline(graphic);
+					graphic = graphic.getNextLeaf() as InlineGraphicElement;
+				}
+			}
+		}
+
+		// Called from composeParagraphElement when we are starting to compose a line. Has hooks to handle floats.
+		protected override function endLine():void
+		{
+			var currentOffset:int = _curElementOffset;
+			var currentElementStart:int = _curElementStart;
+			var element:FlowLeafElement = _curElement;
+			
+			// advance to the next element, using the rootElement of the container as a limitNode
+			// to prevent going past the content bound to this container
+			if (currentOffset >= element.textLength)
+			{
+				// We may have composed ahead over several spans; skip until we match up
+				// Loop until we use catch up to where the line we just composed ended (pos).
+				// Stop if we run out of elements. Skip empty inline elements, and skip floats
+				// that came at the start of the line before any text -- they've already been 
+				// processed.
+				var firstTextSpan:Boolean = true;
+				do{
+					if (element is InlineGraphicElement && InlineGraphicElement(element).float != Float.NONE)
+					{
+						if (!firstTextSpan)
+							composeFloatInline(element as InlineGraphicElement);
+					}
+					else firstTextSpan = false;
+					currentOffset -= element.textLength;
+					currentElementStart  += _curElement.textLength;
+					if (currentElementStart == _curParaStart+_curParaElement.textLength)
+					{
+						break;		// reached end of paragraph
+					}
+					element = element.getNextLeaf();
+				} while (element != null && (currentOffset >= element.textLength || element.textLength == 0 ));
+			}
+		}
+
+	}
+}
diff --git a/textLayout_layout/src/flashx/textLayout/compose/LayoutFlowComposer.as b/textLayout_layout/src/flashx/textLayout/compose/LayoutFlowComposer.as
new file mode 100755
index 0000000..5273d95
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/compose/LayoutFlowComposer.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 flashx.textLayout.compose
+{
+	import __AS3__.vec.Vector;
+	
+	import flash.display.Sprite;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.LayoutContainerController;
+	import flashx.textLayout.events.CompositionCompleteEvent;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+	public class LayoutFlowComposer extends StandardFlowComposer
+	{
+		public function LayoutFlowComposer():void
+		{
+			super();
+		}
+		
+		/** @private */
+		tlf_internal override function getComposeState():ComposeState
+		{ return LayoutComposeState.getLayoutComposeState(); }
+		
+		/** @private */
+		tlf_internal override function releaseComposeState(state:ComposeState):void
+		{ LayoutComposeState.releaseLayoutComposeState(state); }
+		
+		// This override makes the LayoutComposer less efficient but is necessary or floats dissapear if updateAllControllers is called when scrolling
+		// is enabled on the last container.  The base class skips the compose but marks the controllers as needing update.  Since compose was skipped
+		// the inlineChildren arrays are empty and no inlines get composed.  This works around that problem.  A better solution is needed when inlines
+		// become first class and well supported.
+		tlf_internal override function callTheComposer(composeToPosition:int, controllerEndIndex:int):ContainerController
+		{				
+			var state:ComposeState = getComposeState();
+			
+			var lastComposedPosition:int = state.composeTextFlow(textFlow, composeToPosition, controllerEndIndex);
+			if (_damageAbsoluteStart < lastComposedPosition)
+				_damageAbsoluteStart = lastComposedPosition;
+			CONFIG::debug { checkFirstDamaged(); }
+			
+			// make sure there is an empty TextFlowLine covering any trailing content
+			finalizeLinesAfterCompose();
+			
+			releaseComposeState(state);
+							
+			textFlow.dispatchEvent(new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE,false,false,textFlow, 0,lastComposedPosition));
+
+			CONFIG::debug { textFlow.debugCheckTextFlow(); }
+			// TODO: optimize to the first damaged controller
+			return getControllerAt(0);
+		}
+	}
+}
+
diff --git a/textLayout_layout/src/flashx/textLayout/compose/LayoutParcelList.as b/textLayout_layout/src/flashx/textLayout/compose/LayoutParcelList.as
new file mode 100755
index 0000000..31544f9
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/compose/LayoutParcelList.as
@@ -0,0 +1,684 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.compose
+{
+	import flash.geom.Matrix;
+	import flash.geom.Point;
+	import flash.geom.Rectangle;
+	
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.container.IFloatController;
+	import flashx.textLayout.container.IWrapManager;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.formats.BlockProgression;
+	
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;		
+	/** The area inside a text container is sub-divided into smaller areas available for
+	 * text layout. These smaller areas within the container are called Parcels. The 
+	 * ParcelList manages the parcel associated with a TextFlow during composition.
+	 * 
+	 * A container will always have at least one parcel, which corresponds to the container's
+	 * bounding box. If the container has more than one column, each column appears as
+	 * a parcel in the parcel list. If the container has wrap applied, the area around the
+	 * wrap that is available for layout is divided into rectangular-shaped parcels.
+	 * Lastly, parcels may be created during composition for use by flow elements that require
+	 * layout within a specific geometry that may not be the same as the columns: for instance, 
+	 * a straddle head, a table, or a sidehead.
+	 */
+	internal class LayoutParcelList extends ParcelList
+	{	
+		/** This is a list of the wraps, or parcels that are NOT available for text layout. */
+		private var wraps:Array;	/* of Rectangle */
+		
+		/** Inlines can extend across columns, so we have a separate parcel list
+			that is independent of columns (just has container bboxes) used for
+			creating new parcels that can extend across columns. */
+		// private var inlineWrap:LayoutParcelList;
+	
+		/** minimum allowable width of a line */
+		private static const MIN_WIDTH:Number = 40;
+		
+		// a single parcellist that is checked out and checked in
+		static private var _sharedLayoutParcelList:LayoutParcelList;
+
+		/** @private */
+		static tlf_internal function getLayoutParcelList():LayoutParcelList
+		{
+			var rslt:LayoutParcelList = _sharedLayoutParcelList ? _sharedLayoutParcelList : new LayoutParcelList();
+			_sharedLayoutParcelList = null;
+			return rslt;
+		}
+		
+		/** @private */
+		static tlf_internal function releaseLayoutParcelList(list:IParcelList):void
+		{
+			if (_sharedLayoutParcelList == null)
+			{
+				_sharedLayoutParcelList = list as LayoutParcelList;
+				if (_sharedLayoutParcelList)
+					_sharedLayoutParcelList.releaseAnyReferences();
+			}
+		}
+			
+		/** Constructor */
+		public function LayoutParcelList()
+		{
+			super();
+		}
+
+		/** prevent any leaks. @private */
+		tlf_internal override function releaseAnyReferences():void
+		{
+			super.releaseAnyReferences();
+			wraps = null;
+		}
+				
+		override protected function addOneControllerToParcelList(controllerToInitialize:ContainerController):void
+		{
+			super.addOneControllerToParcelList(controllerToInitialize);
+			if (controllerToInitialize is IFloatController)
+			{
+				if (IFloatController(controllerToInitialize).wraps)
+					this.wraps = IFloatController(controllerToInitialize).wraps.wraps;
+				for each (var wrapExclude:Rectangle in wraps)
+					addWrap(wrapExclude, controllerToInitialize, false /* wrap around the sides */);
+			}
+		}
+
+		private function isNextAdjacent():Boolean
+		{
+			// trace("LPL: isNextAdjacent");
+			CONFIG::debug { assert(_currentParcelIndex >= 0 && _currentParcelIndex < numParcels, "invalid _currentParcelIndex in ParcelList"); }
+			if (_currentParcelIndex + 1 >= numParcels)
+				return false;
+			var nextParcel:Parcel = getParcelAtIndex(_currentParcelIndex + 1);
+			if(_blockProgression != BlockProgression.RL)
+			{
+				if (_currentParcel.bottom != nextParcel.top || _currentParcel.left > nextParcel.right)
+					return false;
+			} 
+			else
+			{
+				if(_currentParcel.left != nextParcel.right || _currentParcel.top > nextParcel.bottom)
+					return false;
+			}
+			return true;
+		}
+
+		private function getBBox(controller:ContainerController):Rectangle
+		{
+			// trace("LPL: getBBox");
+			var bbox:Rectangle = null;
+			for (var idx:int = 0; idx < numParcels; idx++)
+			{
+				var p:Parcel = getParcelAtIndex(idx);
+				if (p.controller == controller)
+				{
+					if (!bbox)
+						bbox = p.clone();
+					else
+						bbox = bbox.union(p);
+				}					
+			}
+			return bbox;
+		}
+		
+		private function intersects(r:Rectangle, rectArray:Array):Boolean
+			// true if r intersects any of the rectangles in rectArray
+		{
+			// trace("LPL: getBBox");
+			if (rectArray)
+			{
+				for each (var i:Rectangle in rectArray)
+				{
+					if (i.intersects(r))
+						return true;
+				}
+			}
+			return false;
+		}
+		
+			/** @private */
+		override public function createParcel(parcel:Rectangle, blockProgression:String, verticalJump:Boolean):Boolean
+			// If we can get the requested parcel to fit, create it in the parcels list
+		{
+			// trace("LPL: createParcel");
+		//	trace("createParcel start", parcel.toString());
+		//	traceOut();
+			
+			var fitRect:Rectangle = new Rectangle();
+			do {
+				getLineSlug(fitRect,parcel.height);
+				if (!fitRect || atEnd())	// Can't find contiguous vertical space for the parcel
+					return false;
+				else 
+				{
+					if (blockProgression == BlockProgression.TB)
+						parcel.offset(0, fitRect.top - parcel.top);		// parcel location may have been adjusted by getLineSlug
+					else
+						parcel.offset(fitRect.left - parcel.left, 0);		// parcel location may have been adjusted by getLineSlug
+
+					if (fitRect.width >= parcel.width)
+						break;		// found enough vertical & horizontal space
+
+					// Found vertical space, but not enough horizontal.
+					// It could be that parcel would fit across contiguous columns. Check for a wrap.
+					// Check that it fits within the bounding box for the container, 
+					// and doesn't intersect any wraps	
+					var bbox:Rectangle = getBBox(_currentParcel.controller);
+					if (bbox.containsRect(parcel) && !intersects(parcel, wraps))
+						break;
+
+					next();		// keep looking in other parcels
+
+					if (_currentParcelIndex >= numParcels)
+						return false;		// hit the end: space not found
+				}
+			} while (fitRect.width < parcel.width);
+				
+			// Create a new parcel, and insert it in the correct location in the parcels array
+			var targetController:ContainerController = _currentParcel.controller;
+			addWrap(parcel, targetController, verticalJump /* jumpOver */);
+			for (var l:int = 0; l < numParcels; l++)
+			{
+				var testParcel:Parcel = getParcelAtIndex(l);
+				if (testParcel.top > parcel.top && 
+					!((testParcel.left > parcel.right) || (testParcel.right < parcel.left)))
+				{
+					if (testParcel.controller == targetController)
+						break;
+				}
+			}
+			var splitParcel:Parcel = getParcelAtIndex(l);
+			var splitCoverage:int = splitParcel.columnCoverage;
+			
+			// clear top of column splitParcel is not that anymore
+			splitParcel.columnCoverage = splitCoverage & ~Parcel.TOP_OF_COLUMN;
+			// we're inserting before so its bot_of_column - we aren't
+			insertParcel(l,new Parcel(parcel.x, parcel.y, parcel.width, parcel.height, targetController, splitParcel.column, splitCoverage&~Parcel.BOT_OF_COLUMN));
+
+			// Set the current parcel to be the one we just added
+			_currentParcelIndex = l;
+			_currentParcel = getParcelAtIndex(l);
+			
+	//		trace("createParcel done");
+	//		traceOut();
+				
+			return true;
+		}
+
+		/** @private */
+		override public function getLineSlug(slugRect:Rectangle,height:Number, minWidth:Number = 0):Boolean
+		{
+			return (_currentParcelIndex < numParcels) && getWidthInternal(slugRect, height, minWidth);
+		}
+		
+		/**Helper function for getLineSlug, used internally. Similar to getWidth, but
+		 * although it allows a line to extend across parcels, if necessary, the line
+		 * will always start in the current parce. If a line does not fit starting
+		 * from the current parcel, this function (unlike getWidth) will return
+		 * 0 instead of changing the parcel.
+		 * @param height	amount of contiguous vertical space that must be available
+		 * @param minWidth	amount of contiguous horizontal space that must be available 
+		 * @return amount of contiguous horizontal space actually available
+		 */
+		private function getWidthInternal(slugRect:Rectangle, height:Number, minWidth:Number):Boolean
+		{
+			// trace("LPL: getWidthInternal");
+			CONFIG::debug { assert(_currentParcelIndex >= 0 && _currentParcelIndex < numParcels, "invalid position in ParcelList"); }
+			
+			// See if it fits in the current parcel
+			var tileWidth:Number = getComposeWidth(_currentParcel);
+			if (tileWidth <= minWidth)
+				return false;
+			var requiredHeight:Number = currentParcel.fitAny ? 1 : height;
+			if (currentParcel.composeToPosition || _totalDepth + requiredHeight <= getComposeHeight(_currentParcel))
+			{
+				if (this._blockProgression != BlockProgression.RL)
+				{
+					slugRect.x = left;
+					slugRect.y = _currentParcel.top + _totalDepth;
+					slugRect.width = tileWidth;
+					slugRect.height = height;
+				}
+				else
+				{
+					slugRect.x = left;
+					slugRect.y = _currentParcel.top;
+					slugRect.width = _currentParcel.width-_totalDepth;
+					slugRect.height = tileWidth;
+				}
+				return true;
+			}
+
+			// This tile won't fit in the parcel. Look at the next parcel(s) that are adejacent,
+			// as many as are required fit the tile. The width of the tile will be the minimum
+			// of this list. If the width of the tile is less than the minimum specified by the 
+			// caller, or if there aren't enough adejacent parcels to fit the tile, 
+			// return 0 to indicate the tile doesn't fit in the parcel. The client code can try 
+			// again on the next parcel.
+			var offset:Number = getComposeHeight(_currentParcel) - _totalDepth;
+			var heightRemaining:Number = height - offset;
+			var leftEdge:Number = _currentParcel.left;
+			var rightEdge:Number = _currentParcel.right;
+			var topEdge:Number = _currentParcel.top;
+			if (_blockProgression == BlockProgression.RL)
+				rightEdge -= _totalDepth;
+			else
+				topEdge += _totalDepth;
+			do 
+			{
+				// Next parcel isn't adejacent. We can't fit the tile.
+				if (!isNextAdjacent())
+					return false;
+				next();
+				tileWidth = Math.min(tileWidth, getComposeWidth(_currentParcel));
+				if (tileWidth <= minWidth)
+					return false;	// try again on next tile
+				var newDepth:Number;
+				if (_blockProgression == BlockProgression.RL)
+				{
+					topEdge = Math.max(topEdge, _currentParcel.top);
+					newDepth = -(height - heightRemaining);
+					heightRemaining -= Math.min(heightRemaining, _currentParcel.width);
+				}
+				else
+				{
+					leftEdge = Math.max(leftEdge, _currentParcel.left);
+					newDepth = -(height - heightRemaining);
+					heightRemaining -= Math.min(heightRemaining, _currentParcel.height);
+				}
+			} while (heightRemaining > 0)
+
+			_totalDepth = newDepth;
+			_hasContent = true;
+			
+			slugRect.x = leftEdge;
+			slugRect.y = topEdge;
+			if (_blockProgression == BlockProgression.RL)
+			{
+				slugRect.x = rightEdge - height;
+				slugRect.width = height;
+				slugRect.height = tileWidth;
+			}
+			else
+			{
+				slugRect.width = tileWidth;
+				slugRect.height = height;
+			}
+			return true;
+		}
+		
+		private function getSlugParcel(parcel:Rectangle, blockProgression:String):Rectangle
+		{
+			var fitRect:Rectangle = new Rectangle();
+			do {
+				getLineSlug(fitRect,parcel.height);
+				if (!fitRect || atEnd())	// Can't find contiguous vertical space for the parcel
+					return null;
+				else 
+				{
+					if (blockProgression == BlockProgression.TB)
+						parcel.offset(0, fitRect.top - parcel.top);		// parcel location may have been adjusted by getLineSlug
+					else
+						parcel.offset(fitRect.right - parcel.right, 0);		// parcel location may have been adjusted by getLineSlug
+
+					if (fitRect.width >= parcel.width)
+						break;		// found enough vertical & horizontal space
+
+					// Found vertical space, but not enough horizontal.
+					// It could be that parcel would fit across contiguous columns. Check for a wrap.
+					// Check that it fits within the bounding box for the container, 
+					// and doesn't intersect any wraps	
+					var bbox:Rectangle = getBBox(_currentParcel.controller);
+					if (bbox.containsRect(parcel) && !intersects(parcel, wraps))
+						break;
+
+					next();		// keep looking in other parcels
+
+					if (_currentParcelIndex >= numParcels)
+						return null;		// hit the end: space not found
+				}
+			} while (fitRect.width < parcel.width);
+			return parcel;			
+		}
+		
+		public const NONE:String = "none";			// don't wrap -- allow overlap
+		public const LEFT:String = "left";			// allow text to the left
+		public const RIGHT:String = "right";		// allow text to the right
+	//	public const BIGGEST:String = "biggest";	// wrap either left or right, whichever is a bigger space - not yet supported
+	//	public const BOTH:String = "both";			// "allow text on left and right - BUT jump-overs not supported
+				
+			/** @private */
+		override public function createParcelExperimental(parcel:Rectangle, wrapType:String) : Boolean
+		{
+			// trace("LPL: createParcel");
+		//	trace("createParcel start", parcel.toString());
+		//	traceOut();			
+			parcel = getSlugParcel(parcel, _blockProgression);
+			if (!parcel)
+				return false;	// doesn't fit
+			
+			
+		//	trace("before");
+		//	traceOut();
+		//	trace("parcel", parcel.toString());
+
+			var p:Parcel = getParcelAtIndex(0);
+			var rotationPoint:Point = new Point(p.left, p.top);
+			if (_blockProgression == BlockProgression.RL)
+			{
+				// rotate parcels to TB orientation
+				for (var i:int = 0; i < numParcels; i++)
+				{
+					p = getParcelAtIndex(i);
+					p.replaceBounds(transformRect(p, rotationPoint, true));
+				}	
+				parcel = transformRect(parcel, rotationPoint, true);
+			}
+
+			// Create a new parcel, and insert it in the correct location in the parcels array
+			var targetController:ContainerController = _currentParcel.controller;
+			addWrapExperimental(parcel, targetController, wrapType);
+			_currentParcelIndex = numParcels;
+			_currentParcel = null;
+			for (var l:int = 0; l < numParcels; l++)
+			{
+				p = getParcelAtIndex(l);
+				if (p.equals(parcel))
+				{
+					_currentParcelIndex = l;
+					_currentParcel =  p;
+					break;
+				}
+			}
+			CONFIG::debug { assert (_currentParcelIndex != numParcels, "New parcel not current!"); }
+			
+			if (_blockProgression == BlockProgression.RL)
+			{
+				// rotate back
+				parcel = transformRect(parcel, rotationPoint, false);				
+				for (i = 0; i < numParcels; i++)
+				{
+					p = getParcelAtIndex(i);
+					p.replaceBounds(transformRect(p, rotationPoint, false));
+				}
+			}
+			
+		//	trace("createParcel done");
+		//	traceOut();
+				
+			return true;			
+		}
+		
+		private function transformRect(r:Rectangle, rotationPoint:Point, up:Boolean):Rectangle
+		{
+			var dx:Number = r.x - rotationPoint.x;
+			var dy:Number = (up ? r.y : r.bottom) - rotationPoint.y;
+			if (up)
+				return new Rectangle((rotationPoint.x + dy), (rotationPoint.y - dx) - r.width, r.height, r.width);
+			return new Rectangle((rotationPoint.x - dy), (rotationPoint.y + dx), r.height, r.width);
+		}
+		
+		
+		private function addWrapExperimental(wrap:Rectangle, controller:ContainerController, wrapType:String):void
+		{
+		//	trace("addWrap", wrap.toString());
+		//	traceOut();
+			
+			// Subtracts the wrap from the space available for laying out text.
+			var insertWrap:Boolean = true;
+			var newparcels:Array = new Array();	/* of Parcel */
+			for (var idx:int = 0; idx < numParcels; idx++)
+			{
+				var p:Parcel = getParcelAtIndex(idx);
+				if (p.controller == controller && wrap.intersects(p))
+				{
+					// If the wrap intersects the area, return the unintersected 
+					// part of the area as an array of parcels that replaces
+					// the area. If the area is entirely contained within the wrap,
+					// this will remove the area.
+					//
+					// If the wrap appears inside the area, pick the larger side
+					// to be in the area, and let the smaller side drop out as if
+					// it were part of the wrap. Note that this means we do not
+					// support jump-overs.
+					unintersectExperimental(newparcels, p, wrap, wrapType, insertWrap);
+					insertWrap = false;
+				}
+				else
+					newparcels.push(p);
+			}
+			
+			
+		        // Keep track of the number of wraps per text frame.  It is needed to for vertical alignment.
+		    if (controller.container is IFloatController)
+				IFloatController(controller.container).numWraps++;
+			
+			parcels = newparcels;
+			CONFIG::debug { validate(); }
+		//	trace("after");
+		//	traceOut();
+		}
+		
+		private function unintersectExperimental(result:Array, parcel:Parcel, wrap:Rectangle, wrapType:String, insertWrap:Boolean):void
+		{
+			var area:Rectangle = parcel;
+			// trace("LPL: unintersect");
+			var columnCoverage:int = parcel.columnCoverage;
+						
+			// Return the unintersected part of the area that wrap does not
+			// intersect as an array of parcels
+			var r:Rectangle = area.intersection(wrap);
+			
+			// split into zero, one, two or three chunks
+			var addTopParcel:Boolean = r.top > area.top;
+			var addMidParcel:Boolean = ((r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH)) || (area.right > r.right && area.right - r.right > MIN_WIDTH));
+			var addBotParcel:Boolean = area.bottom > r.bottom;
+			
+			var newCoverage:int;	// scratch for computing coverage
+			
+			var parcelRect:Rectangle;
+			
+			// Space above the intersection
+			if (addTopParcel)
+			{
+				newCoverage = columnCoverage;
+				if (addBotParcel || addMidParcel)
+					newCoverage &= ~Parcel.BOT_OF_COLUMN;
+				columnCoverage &= ~Parcel.TOP_OF_COLUMN;
+				
+				result.push(new Parcel(area.left, area.top, area.width, r.top - area.top, parcel.controller, parcel.column, newCoverage));
+			}
+
+			newCoverage = columnCoverage;
+			if (addBotParcel)
+				newCoverage &= ~Parcel.BOT_OF_COLUMN;
+			columnCoverage &= ~Parcel.TOP_OF_COLUMN;
+
+			// Push our parcel
+			if (insertWrap)
+				result.push(new Parcel(wrap.x, wrap.y, wrap.width, wrap.height, parcel.controller, parcel.column, newCoverage));
+			
+			// Allocate space beside the parcel, depending on wrapType
+			if (wrapType == LEFT)
+			{
+				if (r.left - area.left  > MIN_WIDTH)
+					result.push(new Parcel(area.left, r.top, r.left - area.left, r.height, parcel.controller, parcel.column, newCoverage));
+		}
+			if (wrapType == RIGHT)
+			{
+				if (area.right - r.right  > MIN_WIDTH)
+					result.push(new Parcel(r.right, r.top, area.right - r.right, r.height, parcel.controller, parcel.column, newCoverage));
+			}
+
+			// Space along the bottom
+			if (addBotParcel)
+				result.push(new Parcel(area.left, r.bottom, area.width, area.bottom - r.bottom, parcel.controller, parcel.column, columnCoverage));
+		}
+
+		private function addWrap(wrap:Rectangle, controller:ContainerController, verticalJump:Boolean):void
+		{
+			// trace("LPL: addWrap");
+		//	trace("addWrap", wrap.toString());
+		//	trace("before");
+		//	traceOut();
+			
+			// Subtracts the wrap from the space available for laying out text.
+			var newparcels:Array = new Array();	/* of Parcel */
+			for (var idx:int = 0; idx < numParcels; idx++)
+			{
+				var p:Parcel = getParcelAtIndex(idx);
+				if (p.controller == controller && wrap.intersects(p))
+				{
+					// If the wrap intersects the area, return the unintersected 
+					// part of the area as an array of parcels that replaces
+					// the area. If the area is entirely contained within the wrap,
+					// this will remove the area.
+					//
+					// If the wrap appears inside the area, pick the larger side
+					// to be in the area, and let the smaller side drop out as if
+					// it were part of the wrap. Note that this means we do not
+					// support jump-overs.
+					unintersect(newparcels, p, wrap, verticalJump);
+				//	verticalJump = false; // Yuck! Turning off multiple insertions
+				}
+				else
+					newparcels.push(p);
+			}
+			
+			
+		        // Keep track of the number of wraps per text frame.  It is needed to for vertical alignment.
+		    if (controller.container is IFloatController)
+				IFloatController(controller.container).numWraps++;
+			
+			parcels = newparcels;
+			CONFIG::debug { validate(); }
+		//	trace("after");
+		//	traceOut();
+		}
+		
+		private function unintersect(result:Array, parcel:Parcel, wrap:Rectangle, verticalJump:Boolean):void
+		{
+			// trace("LPL: unintersect");
+			var area:Rectangle = parcel;
+			var columnCoverage:int = parcel.columnCoverage;
+			
+			// Return the unintersected part of the area that wrap does not
+			// intersect as an array of parcels
+			var r:Rectangle = area.intersection(wrap);
+			
+			// split into zero, one, two or three chunks
+			var addTopParcel:Boolean = r.top > area.top;
+			var addMidParcel:Boolean = !verticalJump && ((r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH)) || (area.right > r.right && area.right - r.right > MIN_WIDTH));
+			var addBotParcel:Boolean = area.bottom > r.bottom;
+			
+			var newCoverage:int;	// scratch for computing coverage
+			
+			// Space above the intersection
+			if (addTopParcel)
+			{
+				newCoverage = columnCoverage;
+				if (addBotParcel || addMidParcel)
+					newCoverage &= ~Parcel.BOT_OF_COLUMN;
+				columnCoverage &= ~Parcel.TOP_OF_COLUMN;
+				
+				result.push(new Parcel(area.left, area.top, area.width, r.top - area.top, parcel.controller, parcel.column, newCoverage));
+			}
+			// Space along the left side of the intersection, if the width is great than on the right
+			if (addMidParcel)
+			{
+				newCoverage = columnCoverage;
+				if (addBotParcel)
+					newCoverage &= ~Parcel.BOT_OF_COLUMN;
+				columnCoverage &= ~Parcel.TOP_OF_COLUMN;
+				
+				if (r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH))
+					result.push(new Parcel(area.left, r.top, r.left - area.left, r.height, parcel.controller,  parcel.column, newCoverage));
+				// Space along the right side if that's bigger
+				else // if (area.right > r.right && area.right - r.right > MIN_WIDTH)
+					result.push(new Parcel(r.right, r.top, area.right - r.right, r.height, parcel.controller, parcel.column, newCoverage));
+			}
+			// Space along the bottom
+			if (addBotParcel)
+				result.push(new Parcel(area.left, r.bottom, area.width, area.bottom - r.bottom, parcel.controller, parcel.column, columnCoverage));
+		}
+
+		/** @private */
+		CONFIG::debug private function validate():void
+		{
+			// Check that there are no empty parcels, and that no parcels intersect any other parcel.
+			for (var idx:int; idx < numParcels; idx++)
+			{
+				var i:Parcel = getParcelAtIndex(idx);
+				var parcelRect:Rectangle = i;
+				
+				assert(parcelRect.height != 0 && parcelRect.width != 0, "empty parcel");
+			//	assert(parcelRect.width > MIN_WIDTH, "parcel too small"); we can get a small parcel if we explicitly ask for it (e.g., for a small float)
+				for (var nidx:int; nidx < numParcels; nidx++)
+				{
+					var n:Parcel = getParcelAtIndex(nidx);
+					assert(i == n || i.controller != n.controller || !parcelRect.intersects(n), "parcels intersect");
+				}
+			}
+		}
+		
+		CONFIG::debug {
+			private function traceOut():void
+			{
+				trace("parcels\n");
+				for (var idx:int; idx < numParcels; idx++)
+				{
+					var p:Parcel = getParcelAtIndex(idx);
+					trace(idx.toString(), ":", p, "controller", p.controller);
+				}
+		//		traceRects("wraps\n", wraps);
+			}
+		}
+
+		CONFIG::debug {
+			private function traceRects(description:String, rects:Array):void
+			{
+				trace(description);
+				var count:int = 0;
+				for each (var i:Rectangle in rects)
+				{
+					trace(count.toString(), i);
+					count++;
+				}
+			}
+		}
+		
+		CONFIG::debug {
+			private function traceParcels(description:String, parcels:Array /* of Parcel */):void
+			{
+				trace(description);
+				var count:int = 0;
+				for each (var i:Parcel in parcels)
+				{
+					trace(count.toString(), ":", i, "controller", i.controller);
+					count++;
+				}
+			}
+		}
+
+	}	//end class
+} //end package
diff --git a/textLayout_layout/src/flashx/textLayout/container/IFloatController.as b/textLayout_layout/src/flashx/textLayout/container/IFloatController.as
new file mode 100755
index 0000000..1b87cd5
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/container/IFloatController.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 flashx.textLayout.container
+{
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.geom.Rectangle;
+
+	import flashx.textLayout.container.IWrapManager;
+	
+	/** Controllers that support floats inside the container implement this interface. */
+	public interface IFloatController
+	{
+		/** Add a float to the container. */
+		function recordInlineChild(value:DisplayObject):void;
+
+		/** Figure out how much space a float will require. */
+		function computeInlineArea(value:DisplayObject):Rectangle;		
+
+		function get wraps():IWrapManager;
+		function set wraps(wrapsValue:IWrapManager):void;
+		function get numWraps():int;
+		function set numWraps(value:int):void;
+	}
+}
\ No newline at end of file
diff --git a/textLayout_layout/src/flashx/textLayout/container/IWrapManager.as b/textLayout_layout/src/flashx/textLayout/container/IWrapManager.as
new file mode 100755
index 0000000..14aa9ee
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/container/IWrapManager.as
@@ -0,0 +1,31 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+[ExcludeClass]
+	/** @private The wrap manager keeps track of rectangular text wrap regions.
+	 * A wrap manager keeps track of a list of wraps. 
+	 */
+	public interface IWrapManager
+	{		
+		/** Array of rectangular wraps. Each entry is expected to be a flash rectangle object. */
+		function get wraps():Array;
+		function set wraps(wrapsValue:Array):void;
+	}
+}
\ No newline at end of file
diff --git a/textLayout_layout/src/flashx/textLayout/container/LayoutContainerController.as b/textLayout_layout/src/flashx/textLayout/container/LayoutContainerController.as
new file mode 100755
index 0000000..3de23db
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/container/LayoutContainerController.as
@@ -0,0 +1,253 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 flashx.textLayout.container
+{
+	import flash.display.DisplayObject;
+	import flash.display.DisplayObjectContainer;
+	import flash.display.Sprite;
+	import flash.geom.Rectangle;
+	
+	import flashx.textLayout.compose.IFlowComposer;
+	import flashx.textLayout.compose.LayoutFlowComposer;
+	import flashx.textLayout.conversion.LayoutConfiguration;
+	import flashx.textLayout.debug.assert;
+	import flashx.textLayout.elements.ContainerFormattedElement;
+	import flashx.textLayout.elements.TextFlow;
+	import flashx.textLayout.tlf_internal;
+	
+	use namespace tlf_internal;
+	
+
+	[ExcludeClass]
+	/** @private
+	 *  A container controller to be used for TextFlows that require extended feature set.
+	 */
+	public class LayoutContainerController extends ContainerController implements IFloatController
+	{
+		private var inlineChildren:Array;
+		private var lastInlineChildren:Array = []; // inlineChildren during the last compose pass
+
+		private var _wrapList:IWrapManager;
+				
+		// Composition Results
+		private var _numWraps:int;		// number of wraps in this text frame
+		
+		/** Constructor - creates a new LayoutContainerController instance.
+		 *
+		 * @param cont The DisplayObjectContainer in which to manage the text lines.
+		 * @param compositionWidth The initial width for composing text in the container.
+		 * @param compositionHeight The initial height for composing text in the container.
+		 *
+		 * @playerversion Flash 10
+		 * @playerversion AIR 1.5
+		 * @langversion 3.0
+		 */
+		 
+		public function LayoutContainerController(container:Sprite,compositionWidth:Number=100,compositionHeight:Number=100):void
+		{
+			super(container, compositionWidth, compositionHeight);
+		}
+		
+		public function get wraps():IWrapManager
+		{
+			return _wrapList;
+		}
+		
+		public function set wraps(wrapsValue:IWrapManager):void
+		{
+			if (!(flowComposer is LayoutFlowComposer))
+				throw new Error("Layout feature set requires LayoutConfiguration");
+				
+			_wrapList = wrapsValue;
+			invalidateContents();
+		}
+
+		public function get numWraps():int
+		{
+			return _numWraps;
+		}
+		
+		public function set numWraps(value:int):void
+		{
+			_numWraps = value;
+		}
+			/** @private */
+		override tlf_internal function setRootElement(value:ContainerFormattedElement):void
+		{
+			if (value && wraps != null && !(flowComposer is LayoutFlowComposer))
+				throw new Error("Layout feature set requires LayoutConfiguration");
+				
+			super.setRootElement(value);
+		}						
+
+		/** Find the container of the position in the flow */
+		//--------------------------------------------------------------------------
+		//
+		//  Inlines
+		//
+		//--------------------------------------------------------------------------
+
+		/** inlines */
+		private function addInlineChild(child:DisplayObject):void
+		{
+			if (!container.contains(child))
+			{
+ 				container.addChildAt(child,container.numChildren>0 ? container.numChildren-1 : 0);
+ 			}
+		}
+		private function removeInlineChild(child:DisplayObject):void
+		{
+			// If the graphic was switched from float to inline ("none"), then it has been reparented to a TextLine,
+			// which causes it not to be a child of the container anymore. We catch this as an exception that we handle.
+			try
+			{
+				container.removeChild(child);
+			}
+			catch(e:Error)
+			{
+				if (e.errorID != 2025)
+					throw e;
+			}
+		}
+
+		public function recordInlineChild(value:DisplayObject):void
+		{
+			if (!inlineChildren)
+				inlineChildren = [];
+			else if (inlineChildren.indexOf(value) != -1)
+				return;	// don't read it
+			inlineChildren.push(value);
+		}
+
+		public function computeInlineArea(value:DisplayObject):Rectangle
+		{
+			// HACK
+			var vbc:TextLayoutBaseContainer = value as TextLayoutBaseContainer;
+			if (vbc)
+			{
+				vbc.validateSize();
+				return new Rectangle(0, 0, vbc.width, vbc.height);
+			}
+
+			var cont:DisplayObjectContainer = value as DisplayObjectContainer;
+			
+			// HACK Currently using a few weak typing tricks to play
+			// nicely with Flex components without compiler dependencies.
+			// Undoubtedly there's a better way to do this.
+			if (cont.hasOwnProperty("validateNow"))
+				cont["validateNow"].call(cont);
+			
+			// This moves the container from the rawChildren into the parent container for the purpose of layout
+			// It gets moved back later in updateCompositionShapes/createShapes
+			// TODO: don't do this as its really expensive and forced a complete redraw
+			// cont.includeInLayout = false;
+			if (cont.hasOwnProperty("includeInLayout"))
+				cont["includeInLayout"] = false;
+			// TEMP - force add and remove
+			// if (container.parent != this && container.parent != null)
+			if (cont.parent)
+				cont.parent.removeChild(cont);
+				
+			if (isDamaged())
+			{
+				// temporary hack until appropriate interface is determined
+				if (cont.hasOwnProperty("invalidateSize"))
+					Function(cont["invalidateSize"]).call(cont);
+				//cont.invalidateSize();
+			}
+			if (cont.hasOwnProperty("validateNow"))
+				cont["validateNow"].call(cont);
+			
+			var inlineRect:Rectangle = new Rectangle(0, 0, cont.width, cont.height);
+
+			return inlineRect;
+		}
+		
+		/** @private */
+		override tlf_internal function clearCompositionResults():void
+		{
+			super.clearCompositionResults();
+			
+			clearLastInlineChildren();
+			numWraps = 0;
+		} 
+		
+		private function clearLastInlineChildren():void
+		{
+			if (lastInlineChildren)
+			{
+				for (var i:int = 0; i < lastInlineChildren.length; i++)
+				{
+					var oldInline:DisplayObject = DisplayObject(lastInlineChildren[i]);
+					if ((inlineChildren.indexOf(oldInline) < 0))
+						removeInlineChild(oldInline);
+				}
+			}
+			lastInlineChildren = [];
+		}
+		
+		/** @private */
+		override tlf_internal function updateInlineChildren():void
+		{
+			// Remove the inlines from last time that are not part of what we are going to redisplay this time		
+			clearLastInlineChildren();
+			
+			// synchronize the inline shapes beginning at childIdx
+			// Add in the new shapes from this time that are not already in the list
+			for each (var inline:DisplayObject in inlineChildren)
+			{
+				addInlineChild(inline);
+				
+				// inlines can update themselves if necessary here
+				// We need this because editing a table, e.g., curently invalidates
+				// through the text flow, rather than through the component hierarchy.
+				// (Is this the right thing to do?)
+				if (inline is TextLayoutBaseContainer)
+					TextLayoutBaseContainer(inline).validateNow();	
+			}
+			if (inlineChildren)
+			{
+				lastInlineChildren = inlineChildren.slice();
+				inlineChildren.length = 0;
+			}
+		}
+
+		private function clearInlineSelectionShapes(c:DisplayObjectContainer):void
+		{
+			if (c.hasOwnProperty("controller"))
+				c["controller"].clearAllSelectionShapes();
+			else
+			{
+				for (var idx:int = 0; idx < c.numChildren; idx++)
+				{
+					var child:DisplayObjectContainer = c.getChildAt(idx) as DisplayObjectContainer;
+					if (child)
+						clearInlineSelectionShapes(child);
+				}
+			}
+		}
+		
+		CONFIG::debug tlf_internal override function validateLines():void
+		{
+			// doesn't work in layout yet
+		}
+		
+	}
+}
+
diff --git a/textLayout_layout/src/flashx/textLayout/container/TextLayoutBaseContainer.as b/textLayout_layout/src/flashx/textLayout/container/TextLayoutBaseContainer.as
new file mode 100755
index 0000000..7f11281
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/container/TextLayoutBaseContainer.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 flashx.textLayout.container
+{
+	import flash.display.Sprite;
+
+[ExcludeClass]
+	/** @private */
+	public class TextLayoutBaseContainer extends Sprite
+	{
+		/////////////////////////////////////////////////////////////////////////
+		//  Width and Height
+		/////////////////////////////////////////////////////////////////////////
+
+		private var _width:Number;
+		private var _height:Number;
+
+		// This constructor function is here just to silence a compile warning in Eclipse. There
+		// appears to be no way to turn the warning off selectively.
+		CONFIG::debug public function TextLayoutBaseContainer()
+		{
+			super();
+		}
+		
+		/** @private */
+		override public function get width():Number
+		{
+			return _width;
+		}
+
+		/** @private */
+		override public function set width(value:Number):void
+		{
+			_width = value;
+		}
+
+		/** @private */
+		override public function get height():Number
+		{
+			return _height;
+		}
+
+		/** @private */
+		override public function set height(value:Number):void
+		{
+			_height = value;
+		}
+
+		public function validateSize(recursive:Boolean = false):void
+		{
+			// override		
+		}
+		
+		public function validateNow():void
+		{
+			
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_layout/src/flashx/textLayout/container/WrapManager.as b/textLayout_layout/src/flashx/textLayout/container/WrapManager.as
new file mode 100755
index 0000000..23f4788
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/container/WrapManager.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 flashx.textLayout.container 
+{
+	import flashx.textLayout.container.IWrapManager;
+	
+	[ DefaultProperty("wraps")]
+	public class WrapManager implements IWrapManager
+	{
+		private var _wraps:Array;
+		
+		// This constructor function is here just to silence a compile warning in Eclipse. There
+		// appears to be no way to turn the warning off selectively.
+		CONFIG::debug public function WrapManager()
+		{
+			super();
+		}
+		
+		public function get wraps():Array
+		{
+			return _wraps;
+		}
+		
+		public function set wraps(value:Array):void
+		{
+			_wraps = value;
+		}
+	}
+}
\ No newline at end of file
diff --git a/textLayout_layout/src/flashx/textLayout/conversion/LayoutConfiguration.as b/textLayout_layout/src/flashx/textLayout/conversion/LayoutConfiguration.as
new file mode 100755
index 0000000..676d4db
--- /dev/null
+++ b/textLayout_layout/src/flashx/textLayout/conversion/LayoutConfiguration.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 flashx.textLayout.conversion
+{
+	import flashx.textLayout.compose.LayoutComposeState;
+	import flashx.textLayout.compose.LayoutFlowComposer;
+	import flashx.textLayout.container.ContainerController;
+	import flashx.textLayout.elements.Configuration;
+	import flashx.textLayout.elements.TextFlow;
+	
+	
+	public class LayoutConfiguration 
+	{
+
+		static public function isLayoutComposer(controllerClass:Class) : Boolean
+		{
+			return controllerClass == LayoutFlowComposer;
+		}		
+		
+		/** Set LayoutConfiguration as the default. This updates both the default TextFlow Configuration and the ImportExport configuration for layout support */
+		static public function SetLayoutConfigurationAsDefault():void
+		{
+			TextLayoutImporter.restoreDefaults();
+			var config:ImportExportConfiguration = TextLayoutImporter.defaultConfiguration;
+
+			TextFlow.defaultConfiguration.flowComposerClass = LayoutFlowComposer;
+		}
+	}
+}
\ No newline at end of file