Bug 500331 - Contribute https://github.com/sbrosinski/RegexTester/ to e4

Change-Id: Icce0f01f2bc63539d6f8501180ea91ef41bd4eff
Signed-off-by: Lars Vogel <Lars.Vogel@vogella.com>
diff --git a/bundles/org.eclipse.ui.regex/.classpath b/bundles/org.eclipse.ui.regex/.classpath
new file mode 100644
index 0000000..ad32c83
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.ui.regex/.gitignore b/bundles/org.eclipse.ui.regex/.gitignore
new file mode 100644
index 0000000..ce96585
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+bin
+.settings
diff --git a/bundles/org.eclipse.ui.regex/.project b/bundles/org.eclipse.ui.regex/.project
new file mode 100644
index 0000000..1a0f4a6
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.ui.regex</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.ui.regex/LICENSE.md b/bundles/org.eclipse.ui.regex/LICENSE.md
new file mode 100644
index 0000000..f735bee
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/LICENSE.md
@@ -0,0 +1,203 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+   distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+    i) changes to the Program, and
+   ii) additions to the Program;
+
+   where such changes and/or additions to the Program originate from and are
+   distributed by that particular Contributor. A Contribution 'originates'
+   from a Contributor if it was added to the Program by such Contributor
+   itself or anyone acting on such Contributor's behalf. Contributions do not
+   include additions to the Program which: (i) are separate modules of
+   software distributed in conjunction with the Program under their own
+   license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+  a) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free copyright license to
+     reproduce, prepare derivative works of, publicly display, publicly
+     perform, distribute and sublicense the Contribution of such Contributor,
+     if any, and such derivative works, in source code and object code form.
+  b) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free patent license under
+     Licensed Patents to make, use, sell, offer to sell, import and otherwise
+     transfer the Contribution of such Contributor, if any, in source code and
+     object code form. This patent license shall apply to the combination of
+     the Contribution and the Program if, at the time the Contribution is
+     added by the Contributor, such addition of the Contribution causes such
+     combination to be covered by the Licensed Patents. The patent license
+     shall not apply to any other combinations which include the Contribution.
+     No hardware per se is licensed hereunder.
+  c) Recipient understands that although each Contributor grants the licenses
+     to its Contributions set forth herein, no assurances are provided by any
+     Contributor that the Program does not infringe the patent or other
+     intellectual property rights of any other entity. Each Contributor
+     disclaims any liability to Recipient for claims brought by any other
+     entity based on infringement of intellectual property rights or
+     otherwise. As a condition to exercising the rights and licenses granted
+     hereunder, each Recipient hereby assumes sole responsibility to secure
+     any other intellectual property rights needed, if any. For example, if a
+     third party patent license is required to allow Recipient to distribute
+     the Program, it is Recipient's responsibility to acquire that license
+     before distributing the Program.
+  d) Each Contributor represents that to its knowledge it has sufficient
+     copyright rights in its Contribution, if any, to grant the copyright
+     license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+  a) it complies with the terms and conditions of this Agreement; and
+  b) its license agreement:
+      i) effectively disclaims on behalf of all Contributors all warranties
+         and conditions, express and implied, including warranties or
+         conditions of title and non-infringement, and implied warranties or
+         conditions of merchantability and fitness for a particular purpose;
+     ii) effectively excludes on behalf of all Contributors all liability for
+         damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits;
+    iii) states that any provisions which differ from this Agreement are
+         offered by that Contributor alone and not by any other party; and
+     iv) states that source code for the Program is available from such
+         Contributor, and informs licensees how to obtain it in a reasonable
+         manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+  a) it must be made available under this Agreement; and
+  b) a copy of this Agreement must be included with each copy of the Program.
+     Contributors may not remove or alter any copyright notices contained
+     within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution,
+if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore,
+if a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits and
+other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such Commercial
+Contributor in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any claims
+or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must:
+a) promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such claim at
+its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If
+that Commercial Contributor then makes performance claims, or offers
+warranties related to Product X, those performance claims and warranties are
+such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED 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. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to the
+risks and costs of program errors, compliance with applicable laws, damage to
+or loss of data, programs or equipment, and unavailability or interruption of
+operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by the
+parties hereto, such provision shall be reformed to the minimum extent
+necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted
+under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to
+time. No one other than the Agreement Steward has the right to modify this
+Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+Eclipse Foundation may assign the responsibility to serve as the Agreement
+Steward to a suitable separate entity. Each new version of the Agreement will
+be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version of the
+Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly
+stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+licenses to the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in the
+Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
diff --git a/bundles/org.eclipse.ui.regex/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.regex/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..11b7d4d
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/META-INF/MANIFEST.MF
@@ -0,0 +1,16 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: RegExTester
+Bundle-SymbolicName: org.eclipse.ui.regex;singleton:=true
+Bundle-Version: 1.4
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.eclipse.ui;bundle-version="3.103.0",
+ org.eclipse.ui.ide;bundle-version="3.8.1",
+ org.eclipse.core.runtime;bundle-version="3.8.0",
+ org.eclipse.core.resources;bundle-version="3.8.1"
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.ui.regex.RegExPlugin
+Export-Package: org.eclipse.ui.regex,
+ org.eclipse.ui.regex.event,
+ org.eclipse.ui.regex.view,
+ org.eclipse.ui.regex.view.actions
diff --git a/bundles/org.eclipse.ui.regex/README.md b/bundles/org.eclipse.ui.regex/README.md
new file mode 100644
index 0000000..8d6dae9
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/README.md
@@ -0,0 +1,30 @@
+# RegexTester
+RegexTester is an Eclipse plugin which can be used to easily test regular expressions.
+
+![Screenshot](https://raw.githubusercontent.com/sbrosinski/RegexTester/master/screenshots/regex2.png)
+
+## Features
+
+* Test and search for regular expression
+* Matches are colorized, for an easy visual clue
+* Support for pattern flags (e.g. Pattern.DOTALL)
+* LiveEval evaluates your regular expression while you are typing it, gives feedback on possible errors and shows any matches automatically
+* LiveEval is supported for changes of the regular expression, the search text and the pattern flags
+* 4 distinct match modes:
+  * Find a sequence of characters 
+  * Match a complete text
+  * Split text
+  * Replace every occurence of the regex with a different string. Replacing supports back references ($1,$2,...)
+* LiveEval for match mode changes
+* Context sensitive "Regular Expression Assist"
+* Selective evaluation of expressions
+* Bracket Matching
+* Generation of string literals based on the regexp, e.g. "\(x\)" becomes "\\(x\\)"
+* De-escape patterns in your code, e.g. \\(x\\) becomes \(x\)
+* Improved "Clear Menu", choose which parts of the view you would like to get cleared every time you press the clear button
+* Easy movement through matches: Choose "Previous Match" or "Next Match" and cycle through all matches found.
+* Polished and accessible user interface, everything is reachable via keyboard
+
+## Installation
+
+[Download the plugin jar](https://github.com/sbrosinski/RegexTester/downloads) and put it in your Eclipse plugin folder.
diff --git a/bundles/org.eclipse.ui.regex/build.properties b/bundles/org.eclipse.ui.regex/build.properties
new file mode 100644
index 0000000..588f2c4
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/build.properties
@@ -0,0 +1,13 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               icons/,\
+               lib/,\
+               README.md,\
+               plugin.xml
+src.includes = icons/,\
+               lib/,\
+               src/,\
+               plugin.xml,\
+               build.properties
diff --git a/bundles/org.eclipse.ui.regex/epl-v10.html b/bundles/org.eclipse.ui.regex/epl-v10.html
new file mode 100644
index 0000000..894064c
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/epl-v10.html
@@ -0,0 +1,259 @@
+<!--?xml version="1.0" encoding="ISO-8859-1" ?-->

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

+<html xmlns="http://www.w3.org/1999/xhtml"><head>

+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">

+<title>Eclipse Public License - Version 1.0</title>

+<style type="text/css">

+  body {

+    size: 8.5in 11.0in;

+    margin: 0.25in 0.5in 0.25in 0.5in;

+    tab-interval: 0.5in;

+    }

+  p {  	

+    margin-left: auto;

+    margin-top:  0.5em;

+    margin-bottom: 0.5em;

+    }

+  p.list {

+  	margin-left: 0.5in;

+    margin-top:  0.05em;

+    margin-bottom: 0.05em;

+    }

+  </style>

+

+</head>

+

+<body lang="EN-US">

+

+<h2>Eclipse Public License - v 1.0</h2>

+

+<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE

+PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR

+DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS

+AGREEMENT.</p>

+

+<p><b>1. DEFINITIONS</b></p>

+

+<p>"Contribution" means:</p>

+

+<p class="list">a) in the case of the initial Contributor, the initial

+code and documentation distributed under this Agreement, and</p>

+<p class="list">b) in the case of each subsequent Contributor:</p>

+<p class="list">i) changes to the Program, and</p>

+<p class="list">ii) additions to the Program;</p>

+<p class="list">where such changes and/or additions to the Program

+originate from and are distributed by that particular Contributor. A

+Contribution 'originates' from a Contributor if it was added to the

+Program by such Contributor itself or anyone acting on such

+Contributor's behalf. Contributions do not include additions to the

+Program which: (i) are separate modules of software distributed in

+conjunction with the Program under their own license agreement, and (ii)

+are not derivative works of the Program.</p>

+

+<p>"Contributor" means any person or entity that distributes

+the Program.</p>

+

+<p>"Licensed Patents" mean patent claims licensable by a

+Contributor which are necessarily infringed by the use or sale of its

+Contribution alone or when combined with the Program.</p>

+

+<p>"Program" means the Contributions distributed in accordance

+with this Agreement.</p>

+

+<p>"Recipient" means anyone who receives the Program under

+this Agreement, including all Contributors.</p>

+

+<p><b>2. GRANT OF RIGHTS</b></p>

+

+<p class="list">a) Subject to the terms of this Agreement, each

+Contributor hereby grants Recipient a non-exclusive, worldwide,

+royalty-free copyright license to reproduce, prepare derivative works

+of, publicly display, publicly perform, distribute and sublicense the

+Contribution of such Contributor, if any, and such derivative works, in

+source code and object code form.</p>

+

+<p class="list">b) Subject to the terms of this Agreement, each

+Contributor hereby grants Recipient a non-exclusive, worldwide,

+royalty-free patent license under Licensed Patents to make, use, sell,

+offer to sell, import and otherwise transfer the Contribution of such

+Contributor, if any, in source code and object code form. This patent

+license shall apply to the combination of the Contribution and the

+Program if, at the time the Contribution is added by the Contributor,

+such addition of the Contribution causes such combination to be covered

+by the Licensed Patents. The patent license shall not apply to any other

+combinations which include the Contribution. No hardware per se is

+licensed hereunder.</p>

+

+<p class="list">c) Recipient understands that although each Contributor

+grants the licenses to its Contributions set forth herein, no assurances

+are provided by any Contributor that the Program does not infringe the

+patent or other intellectual property rights of any other entity. Each

+Contributor disclaims any liability to Recipient for claims brought by

+any other entity based on infringement of intellectual property rights

+or otherwise. As a condition to exercising the rights and licenses

+granted hereunder, each Recipient hereby assumes sole responsibility to

+secure any other intellectual property rights needed, if any. For

+example, if a third party patent license is required to allow Recipient

+to distribute the Program, it is Recipient's responsibility to acquire

+that license before distributing the Program.</p>

+

+<p class="list">d) Each Contributor represents that to its knowledge it

+has sufficient copyright rights in its Contribution, if any, to grant

+the copyright license set forth in this Agreement.</p>

+

+<p><b>3. REQUIREMENTS</b></p>

+

+<p>A Contributor may choose to distribute the Program in object code

+form under its own license agreement, provided that:</p>

+

+<p class="list">a) it complies with the terms and conditions of this

+Agreement; and</p>

+

+<p class="list">b) its license agreement:</p>

+

+<p class="list">i) effectively disclaims on behalf of all Contributors

+all warranties and conditions, express and implied, including warranties

+or conditions of title and non-infringement, and implied warranties or

+conditions of merchantability and fitness for a particular purpose;</p>

+

+<p class="list">ii) effectively excludes on behalf of all Contributors

+all liability for damages, including direct, indirect, special,

+incidental and consequential damages, such as lost profits;</p>

+

+<p class="list">iii) states that any provisions which differ from this

+Agreement are offered by that Contributor alone and not by any other

+party; and</p>

+

+<p class="list">iv) states that source code for the Program is available

+from such Contributor, and informs licensees how to obtain it in a

+reasonable manner on or through a medium customarily used for software

+exchange.</p>

+

+<p>When the Program is made available in source code form:</p>

+

+<p class="list">a) it must be made available under this Agreement; and</p>

+

+<p class="list">b) a copy of this Agreement must be included with each

+copy of the Program.</p>

+

+<p>Contributors may not remove or alter any copyright notices contained

+within the Program.</p>

+

+<p>Each Contributor must identify itself as the originator of its

+Contribution, if any, in a manner that reasonably allows subsequent

+Recipients to identify the originator of the Contribution.</p>

+

+<p><b>4. COMMERCIAL DISTRIBUTION</b></p>

+

+<p>Commercial distributors of software may accept certain

+responsibilities with respect to end users, business partners and the

+like. While this license is intended to facilitate the commercial use of

+the Program, the Contributor who includes the Program in a commercial

+product offering should do so in a manner which does not create

+potential liability for other Contributors. Therefore, if a Contributor

+includes the Program in a commercial product offering, such Contributor

+("Commercial Contributor") hereby agrees to defend and

+indemnify every other Contributor ("Indemnified Contributor")

+against any losses, damages and costs (collectively "Losses")

+arising from claims, lawsuits and other legal actions brought by a third

+party against the Indemnified Contributor to the extent caused by the

+acts or omissions of such Commercial Contributor in connection with its

+distribution of the Program in a commercial product offering. The

+obligations in this section do not apply to any claims or Losses

+relating to any actual or alleged intellectual property infringement. In

+order to qualify, an Indemnified Contributor must: a) promptly notify

+the Commercial Contributor in writing of such claim, and b) allow the

+Commercial Contributor to control, and cooperate with the Commercial

+Contributor in, the defense and any related settlement negotiations. The

+Indemnified Contributor may participate in any such claim at its own

+expense.</p>

+

+<p>For example, a Contributor might include the Program in a commercial

+product offering, Product X. That Contributor is then a Commercial

+Contributor. If that Commercial Contributor then makes performance

+claims, or offers warranties related to Product X, those performance

+claims and warranties are such Commercial Contributor's responsibility

+alone. Under this section, the Commercial Contributor would have to

+defend claims against the other Contributors related to those

+performance claims and warranties, and if a court requires any other

+Contributor to pay any damages as a result, the Commercial Contributor

+must pay those damages.</p>

+

+<p><b>5. NO WARRANTY</b></p>

+

+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS

+PROVIDED 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. Each Recipient is solely

+responsible for determining the appropriateness of using and

+distributing the Program and assumes all risks associated with its

+exercise of rights under this Agreement , including but not limited to

+the risks and costs of program errors, compliance with applicable laws,

+damage to or loss of data, programs or equipment, and unavailability or

+interruption of operations.</p>

+

+<p><b>6. DISCLAIMER OF LIABILITY</b></p>

+

+<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT

+NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,

+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING

+WITHOUT LIMITATION LOST PROFITS), 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 OR

+DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED

+HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>

+

+<p><b>7. GENERAL</b></p>

+

+<p>If any provision of this Agreement is invalid or unenforceable under

+applicable law, it shall not affect the validity or enforceability of

+the remainder of the terms of this Agreement, and without further action

+by the parties hereto, such provision shall be reformed to the minimum

+extent necessary to make such provision valid and enforceable.</p>

+

+<p>If Recipient institutes patent litigation against any entity

+(including a cross-claim or counterclaim in a lawsuit) alleging that the

+Program itself (excluding combinations of the Program with other

+software or hardware) infringes such Recipient's patent(s), then such

+Recipient's rights granted under Section 2(b) shall terminate as of the

+date such litigation is filed.</p>

+

+<p>All Recipient's rights under this Agreement shall terminate if it

+fails to comply with any of the material terms or conditions of this

+Agreement and does not cure such failure in a reasonable period of time

+after becoming aware of such noncompliance. If all Recipient's rights

+under this Agreement terminate, Recipient agrees to cease use and

+distribution of the Program as soon as reasonably practicable. However,

+Recipient's obligations under this Agreement and any licenses granted by

+Recipient relating to the Program shall continue and survive.</p>

+

+<p>Everyone is permitted to copy and distribute copies of this

+Agreement, but in order to avoid inconsistency the Agreement is

+copyrighted and may only be modified in the following manner. The

+Agreement Steward reserves the right to publish new versions (including

+revisions) of this Agreement from time to time. No one other than the

+Agreement Steward has the right to modify this Agreement. The Eclipse

+Foundation is the initial Agreement Steward. The Eclipse Foundation may

+assign the responsibility to serve as the Agreement Steward to a

+suitable separate entity. Each new version of the Agreement will be

+given a distinguishing version number. The Program (including

+Contributions) may always be distributed subject to the version of the

+Agreement under which it was received. In addition, after a new version

+of the Agreement is published, Contributor may elect to distribute the

+Program (including its Contributions) under the new version. Except as

+expressly stated in Sections 2(a) and 2(b) above, Recipient receives no

+rights or licenses to the intellectual property of any Contributor under

+this Agreement, whether expressly, by implication, estoppel or

+otherwise. All rights in the Program not expressly granted under this

+Agreement are reserved.</p>

+

+<p>This Agreement is governed by the laws of the State of New York and

+the intellectual property laws of the United States of America. No party

+to this Agreement will bring a legal action under this Agreement more

+than one year after the cause of action arose. Each party waives its

+rights to a jury trial in any resulting litigation.</p>

+

+

+

+</body></html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/icons/backward_nav.gif b/bundles/org.eclipse.ui.regex/icons/backward_nav.gif
new file mode 100644
index 0000000..740419b
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/backward_nav.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/icons/clear_co.gif b/bundles/org.eclipse.ui.regex/icons/clear_co.gif
new file mode 100644
index 0000000..2558326
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/clear_co.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/icons/e.gif b/bundles/org.eclipse.ui.regex/icons/e.gif
new file mode 100644
index 0000000..7244b85
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/e.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/icons/forward_nav.gif b/bundles/org.eclipse.ui.regex/icons/forward_nav.gif
new file mode 100644
index 0000000..7a1511d
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/forward_nav.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/icons/nag.gif b/bundles/org.eclipse.ui.regex/icons/nag.gif
new file mode 100644
index 0000000..afee6cb
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/nag.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/icons/sample.gif b/bundles/org.eclipse.ui.regex/icons/sample.gif
new file mode 100644
index 0000000..34fb3c9
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/icons/sample.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/lib/xstream-1.0.2.jar b/bundles/org.eclipse.ui.regex/lib/xstream-1.0.2.jar
new file mode 100644
index 0000000..ca614c8
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/lib/xstream-1.0.2.jar
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/plugin.xml b/bundles/org.eclipse.ui.regex/plugin.xml
new file mode 100644
index 0000000..9735cbd
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/plugin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<?eclipse version="3.0"?>

+<plugin>

+ 

+   <extension

+         point="org.eclipse.ui.views">

+      <category

+            name="RegEx Tester"

+            id="org.eclipse.ui.regex.cat">

+      </category>

+      <view

+            name="RegEx Tester"

+            icon="icons/e.gif"

+            category="org.eclipse.ui.regex.cat"

+            class="org.eclipse.ui.regex.view.RegExView"

+            id="org.eclipse.ui.regex.view.RegExView">

+      </view>

+   </extension>

+   

+      

+   

+   <extension

+         point="org.eclipse.ui.preferencePages">

+      <page

+            name="RegEx Tester"

+            class="org.eclipse.ui.regex.view.RegExPreferencePage"

+            id="org.eclipse.ui.regex.view.RegExPreferencePage">

+      </page>

+   </extension>

+

+   <extension

+         point="org.eclipse.ui.preferencePages">

+      <page

+            name="Fonts"

+            class="org.eclipse.ui.regex.view.FontPreferencePage"

+            id="org.eclipse.ui.regex.view.FontPreferencePage"

+            category="org.eclipse.ui.regex.view.RegExPreferencePage">

+            

+      </page>

+   </extension>

+  

+

+</plugin>

diff --git a/bundles/org.eclipse.ui.regex/screenshots/regex2.png b/bundles/org.eclipse.ui.regex/screenshots/regex2.png
new file mode 100644
index 0000000..ebb15e3
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/screenshots/regex2.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Group.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Group.java
new file mode 100644
index 0000000..8caf2ec
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Group.java
@@ -0,0 +1,39 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+

+public class Group {

+	

+	private int index;

+	private String text;

+	

+	public Group(int index, String text) {

+		this.index = index;

+		this.text = text;

+	}

+	

+	

+

+	/**

+	 * @return Returns the index.

+	 */

+	public int getIndex() {

+		return index;

+	}

+	/**

+	 * @return Returns the text.

+	 */

+	public String getText() {

+		return text;

+	}

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/IRegExListener.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/IRegExListener.java
new file mode 100644
index 0000000..2a7dbec
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/IRegExListener.java
@@ -0,0 +1,25 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+import org.eclipse.ui.regex.event.IListener;

+

+

+public interface IRegExListener extends IListener {

+	

+	public void foundMatches(Matches matches);

+	public void foundNoMatches();

+	public void expressionError(String errMsg);

+	public void doneWithReplace(ReplaceResult result);

+	public void doneWithSplit(String[] result);

+    public void updateRequested();

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Match.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Match.java
new file mode 100644
index 0000000..8fca7b6
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Match.java
@@ -0,0 +1,114 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+import java.util.ArrayList;

+import java.util.List;

+

+/**

+ * Defines a single match with was found.

+ * @author sbrosinski

+ * @version $$Id: Match.java,v 1.4 2004/06/15 11:49:17 sbrosin Exp $$

+ */

+ 

+public class Match {

+	/** the match's start index within the search text */ 

+	private int	start_;

+	/** the match's end index within the search text */ 	

+	private int	end_;

+

+	/** contains the match text actually found */ 

+	private String text_;

+

+	private ArrayList groups_;

+

+	/**

+	 * Construct a Match.

+	 * @param id	an id, identifying the match uniquely

+	 * @param start the match's start index within the search text

+	 * @param end   the match's end index within the search text 

+	 * @param text  contains the match text actually found

+	 */

+	public Match(int start, int end, String text) {

+		start_ 	= start;

+		end_ 	= end;

+		text_	= text;

+		groups_ = new ArrayList();

+	}

+

+	public void addGroup(Group group) {

+		groups_.add(group);

+	}

+

+	public int getGroupCount() {

+		return groups_.size();

+	}

+	

+	public List getGroups() {

+		return groups_;

+	}

+

+	/**

+	 * Gets the end index of found match.

+	 * @return end index of found match

+	 */

+	public int getEnd() {

+		return end_;

+	}

+

+

+	/**

+	 * Gets the start index of found match.

+	 * @return start index of found match

+	 */

+	public int getStart() {

+		return start_;

+	}

+

+

+	/**

+	 * Gets the match text.

+	 * @return the match text

+	 */

+	public String getText() {

+		return text_;

+	}

+

+

+

+	/**

+	 * Sets the end end index of found match.

+	 * @param end end index of found match

+	 */

+	public void setEnd(int end) {

+		end_ = end;

+	}

+

+

+	/**

+	 * Sets the start end index of found match.

+	 * @param start start index of found match

+	 */

+	public void setStart(int start) {

+		start_ = start;

+	}

+

+

+	/**

+	 * Sets the match text.

+	 * @param text the match text

+	 */

+	public void setText(String text) {

+		text_ = text;

+	}

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Matches.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Matches.java
new file mode 100644
index 0000000..a2a3a15
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/Matches.java
@@ -0,0 +1,130 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+import java.util.ArrayList;

+import java.util.Iterator;

+

+

+/**

+ * Encapsulates all matches found during a single matching session. 

+ * @author sbrosinski

+ * @version $$Id: Matches.java,v 1.6 2004/09/06 10:35:16 sbrosin Exp $$

+ */

+public class Matches {

+

+	/** a list containing all matches. */

+	private ArrayList	matchList_;

+	

+	/** virtual marker, can be set to a certain position within the matches

+	 *  list. Is used to provide previousMatch/nextMatch result scrolling.

+	 * */

+	private int			posMarker_;

+

+

+	/**

+	 * Constructs a new Matches object.

+	 */

+	public Matches() {

+		matchList_ = new ArrayList();

+		// set position marker "in front" of list

+		posMarker_ = -1;

+	}

+

+	public Iterator iterator() {

+	    return matchList_.iterator();

+	}

+	

+	

+	/**

+	 * Gets the number of matches found.

+	 * @return number of matches.

+	 */

+	public int getMatchCount() {

+		return matchList_.size();

+	}

+

+

+	/** 

+	 * Gets the postion of the internal list marker.

+	 * @return position, 0 to numberOfMatches-1

+	 */

+	public int getMatchPos() {

+		return posMarker_;

+	}

+

+

+	/**

+	 * Returns the match found for a certain range withing the

+	 * search text.

+	 * @param start the range's start index

+	 * @param end	the range's end index

+	 * @return one Match or null, if no match was found

+	 */

+	public Match getMatchByRange(int start, int end) {

+		for (int i = 0; i < matchList_.size(); i++) {

+			Match match = (Match) matchList_.get(i);

+			if (start >= match.getStart() && end <= match.getEnd())

+				return match;

+		}

+		return null;

+	}

+

+

+	public void addMatch(Match match) {

+		matchList_.add(match);

+	}

+

+

+	public Match nextMatch() {

+		if (matchList_ == null)

+			return null;

+

+		if (!(posMarker_ + 1 > matchList_.size() - 1)) {

+			posMarker_++;

+			Match match = (Match) matchList_.get(posMarker_);

+			return match;

+		}

+

+		return null;

+	}

+

+

+	public Match prevMatch() {

+		if (matchList_ == null)

+			return null;

+

+		if (!(posMarker_ - 1 < 0)) {

+			posMarker_--;

+			Match match = (Match) matchList_.get(posMarker_);

+			return match;

+		}

+

+		return null;

+	}

+

+

+	public void resetMatchPos() {

+		posMarker_ = -1;

+	}

+

+

+	public void setMatchPos(int pos) {

+		posMarker_ = pos;

+	}

+

+

+	public void reset() {

+		matchList_ = new ArrayList();

+	}

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExListenerManager.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExListenerManager.java
new file mode 100644
index 0000000..678eb6e
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExListenerManager.java
@@ -0,0 +1,63 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex;

+

+import java.util.Iterator;

+

+import org.eclipse.ui.regex.event.ListenerManager;

+

+public class RegExListenerManager extends ListenerManager {

+	

+	public void publishExpressionError(String errMsg) {

+		for (Iterator i = getListeners().iterator(); i.hasNext();) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.expressionError(errMsg);

+		}

+	}

+

+	public void publishFoundMatches(Matches foundMatches) {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.foundMatches(foundMatches);

+		}

+	}

+

+	public void publishFoundNoMatches() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.foundNoMatches();

+		}

+	}

+	

+	public void publishDoneWithReplace(ReplaceResult result) {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.doneWithReplace(result);

+		}

+	}

+	

+	public void publishDoneWithSplit(String[] result) {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.doneWithSplit(result);

+		}

+	}

+	

+	public void updateRequested() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			IRegExListener listener = (IRegExListener) i.next();

+			listener.updateRequested();

+		}

+	}	

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExModel.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExModel.java
new file mode 100644
index 0000000..6410420
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExModel.java
@@ -0,0 +1,287 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+import java.util.regex.Matcher;

+import java.util.regex.Pattern;

+import java.util.regex.PatternSyntaxException;

+

+public class RegExModel {

+

+    private static RegExModel _instance;

+

+    public final static int MODE_FIND = 0;

+

+    public final static int MODE_MATCH = 1;

+

+    public final static int MODE_SPLIT = 2;

+

+    public final static int MODE_REPLACE = 3;

+

+    private int patternFlags;

+

+    private Matches matches;

+

+    private boolean foundMatches;

+

+    private int matchMode;

+

+    private String replace;

+

+    private String _regExp;

+

+    private String _searchText;

+

+    private RegExListenerManager regExListenerManager;

+

+    private String description;

+    

+    private RegExModel() {

+        matches = new Matches();

+        matchMode = MODE_FIND;

+        patternFlags = 0;

+        foundMatches = false;

+        regExListenerManager = new RegExListenerManager();

+    }

+

+    public static RegExModel getInstance() {

+        if (_instance == null) {

+            _instance = new RegExModel();

+        }

+        return _instance;

+    }

+

+    public int getMatchMode() {

+        return matchMode;

+    }

+    

+    public void requestUpdate() {

+        regExListenerManager.updateRequested();

+    }

+    

+    public void addRegExListener(IRegExListener listener) {

+    	regExListenerManager.addListener(listener);

+    }

+

+    public void removeRegExListener(IRegExListener listener) {

+    	regExListenerManager.removeListener(listener);

+    }

+

+    public void process() {

+        foundMatches = false;

+        matches = new Matches();

+        if (_regExp.equals("") || _searchText.equals("")) {

+        	regExListenerManager.publishFoundNoMatches();

+            return;

+        }

+        try {

+            Pattern pattern = Pattern.compile(_regExp, getPatternFlags());

+            Matcher match = pattern.matcher(_searchText);

+            switch (matchMode) {

+            case MODE_FIND: {

+                find(match);

+                break;

+            }

+            case MODE_MATCH: {

+                match(match);

+                break;

+            }

+            case MODE_REPLACE: {

+                replace(match);

+                break;

+            }

+            case MODE_SPLIT: {

+                split(match, pattern);

+                break;

+            }

+            }

+        } catch (PatternSyntaxException patternSyntaxException) {

+        	regExListenerManager.publishExpressionError(patternSyntaxException.getMessage());

+        }

+    }

+

+    private void find(Matcher match) {

+        if (processMatches(match)) {

+        	regExListenerManager.publishFoundMatches(matches);

+        } else {

+        	regExListenerManager.publishFoundNoMatches();

+        }

+    }

+    

+    private void match(Matcher match) {

+

+        if (match.matches()) {

+            foundMatches = true;

+            matches.addMatch(new Match(match.start(), match.end(), match

+                    .group(0)));

+            regExListenerManager.publishFoundMatches(matches);

+        } else {

+        	regExListenerManager.publishFoundNoMatches();

+        }

+

+    }

+

+    private boolean processMatches(Matcher match) {

+        while (match.find()) {

+            foundMatches = true;

+

+            Match aMatch = new Match(match.start(), match.end(), match.group(0));

+            for (int i = 0; i < match.groupCount() + 1; i++) {

+                aMatch.addGroup(new Group(i, match.group(i)));

+            }

+            matches.addMatch(aMatch);

+        }

+        return foundMatches;

+    }

+

+    private void replace(Matcher match) {

+        if (replace != null) {

+            if (processMatches(match)) {

+                String resultText = match.replaceAll(replace);

+                regExListenerManager.publishDoneWithReplace(new ReplaceResult(resultText, matches));

+            } else {

+            	regExListenerManager.publishFoundNoMatches();

+            }

+        }

+    }

+

+

+    private void split(Matcher match, Pattern pattern) {

+        if (processMatches(match)) {

+        	regExListenerManager.publishFoundMatches(matches);

+        	regExListenerManager.publishDoneWithSplit(pattern.split(_searchText));        

+        } else {

+        	regExListenerManager.publishFoundNoMatches();

+        }

+    }    

+    

+

+    public void setMatchMode(int mode) {

+        matchMode = mode;

+    }

+

+    public void setReplace(String theReplace) {

+        replace = theReplace;

+    }

+

+    public String getReplace() {

+        return replace;

+    }

+

+    public void reset() {

+        foundMatches = false;

+        matches = new Matches();

+        _regExp = "";

+        _searchText = "";

+    }

+

+    public boolean foundMatches() {

+        return foundMatches;

+    }

+

+    public Matches getMatches() {

+        return matches;

+    }

+

+    public void addPatternFlag(int flag) {

+        patternFlags += flag;

+    }

+

+    public void removePatternFlag(int flag) {

+        patternFlags -= flag;

+    }

+

+    public void resetPatternFlag() {

+        patternFlags = 0;

+    }

+

+    public int getPatternFlags() {

+        return patternFlags;

+    }

+

+    public String getPatternFlagsAsString() {

+        if (patternFlags == 0)

+            return "";

+        StringBuffer out = new StringBuffer();

+        if ((patternFlags & Pattern.CANON_EQ) != 0)

+            out.append("Pattern.CANON_EQ+");

+        if ((patternFlags & Pattern.CASE_INSENSITIVE) != 0)

+            out.append("Pattern.CASE_INSENSITIVE+");

+        if ((patternFlags & Pattern.COMMENTS) != 0)

+            out.append("Pattern.COMMENTS+");

+        if ((patternFlags & Pattern.DOTALL) != 0)

+            out.append("Pattern.DOTALL+");

+        if ((patternFlags & Pattern.MULTILINE) != 0)

+            out.append("Pattern.MULTILINE+");

+        if ((patternFlags & Pattern.UNICODE_CASE) != 0)

+            out.append("Pattern.UNICODE_CASE+");

+        if ((patternFlags & Pattern.UNIX_LINES) != 0)

+            out.append("Pattern.UNIX_LINES+");

+        String outStr = out.toString();

+        return outStr.substring(0, outStr.length() - 1);

+    }

+

+    public String getRegExAsLiteral() {

+        StringBuffer out = new StringBuffer();

+        char[] chars = getRegExp().toCharArray();

+        for (int i = 0; i < chars.length; i++) {

+            if (chars[i] == '\\') {

+                out.append("\\\\");

+            } else if (chars[i] == '"') {

+                out.append("\\\"");

+            } else {

+                out.append(chars[i]);

+            }

+        }

+        return out.toString();

+    }

+

+    /**

+     * @return Returns the _regExp.

+     */

+    public String getRegExp() {

+        return _regExp;

+    }

+

+    /**

+     * @param exp The _regExp to set.

+     */

+    public void setRegExp(String exp) {

+        _regExp = exp;

+    }

+

+    /**

+     * @return Returns the _searchText.

+     */

+    public String getSearchText() {

+        return _searchText;

+    }

+

+    /**

+     * @param text The _searchText to set.

+     */

+    public void setSearchText(String text) {

+        _searchText = text;

+    }

+

+    /**

+     * @param descr

+     */

+    public void setDescription(String description) {

+        this.description = description;        

+    }

+    

+    public String getDescription() {

+        return description;

+    }

+    

+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExPlugin.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExPlugin.java
new file mode 100644
index 0000000..c4cbf7e
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/RegExPlugin.java
@@ -0,0 +1,120 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+import java.util.MissingResourceException;

+import java.util.ResourceBundle;

+

+import org.eclipse.jface.resource.ImageDescriptor;

+import org.eclipse.swt.graphics.FontData;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.ui.plugin.AbstractUIPlugin;

+import org.osgi.framework.BundleContext;

+

+

+public class RegExPlugin extends AbstractUIPlugin {

+

+	private static RegExPlugin plugin;

+	

+	//Resource bundle.

+	private ResourceBundle resourceBundle;

+	

+	/**

+	 * The constructor.

+	 */

+	public RegExPlugin() {

+	}

+

+	/**

+	 * This method is called upon plug-in activation

+	 */

+	public void start(BundleContext context) throws Exception {

+		super.start(context);

+		plugin = this;

+		try {

+			resourceBundle = ResourceBundle.getBundle("org.eclipse.ui.regex.PluginResources");

+		} catch (MissingResourceException x) {

+			resourceBundle = null;

+		}

+	}

+

+	/**

+	 * This method is called when the plug-in is stopped

+	 */

+	public void stop(BundleContext context) throws Exception {

+		plugin = null;

+		resourceBundle = null;

+		super.stop(context);

+	}

+

+	/**

+	 * Returns the shared instance.

+	 */

+	public static RegExPlugin getDefault() {

+		return plugin;

+	}

+

+	/**

+	 * Returns the string from the plugin's resource bundle,

+	 * or 'key' if not found.

+	 */

+	public static String getResourceString(String key) {

+		ResourceBundle bundle = RegExPlugin.getDefault().getResourceBundle();

+		try {

+			return (bundle != null) ? bundle.getString(key) : key;

+		} catch (MissingResourceException e) {

+			return key;

+		}

+	}

+

+	/**

+	 * Returns the plugin's resource bundle,

+	 */

+	public ResourceBundle getResourceBundle() {

+		return resourceBundle;

+	}

+	

+

+	

+	protected void initializeDefaultPluginPreferences() {

+		getPreferenceStore().setDefault("Pattern.CANON_EQ",false);

+		getPreferenceStore().setDefault("Pattern.CASE_INSENSITIVE",false);

+		getPreferenceStore().setDefault("Pattern.COMMENTS",false);

+		getPreferenceStore().setDefault("Pattern.DOTALL",false);

+		getPreferenceStore().setDefault("Pattern.MULTILINE",false);

+		getPreferenceStore().setDefault("Pattern.UNICODE_CASE",false);

+		getPreferenceStore().setDefault("Pattern.UNIX_LINES",false);

+		getPreferenceStore().setDefault("EvalRegEx",false);

+		getPreferenceStore().setDefault("EvalSearch",false);

+		getPreferenceStore().setDefault("EvalBoth",true);

+		getPreferenceStore().setDefault("EvalSwitch",false);

+		

+		FontData systemFont = Display.getCurrent().getSystemFont().getFontData()[0];

+		

+		getPreferenceStore().setDefault("font.regex.name", systemFont.getName());

+		getPreferenceStore().setDefault("font.regex.height", systemFont.getHeight());

+		getPreferenceStore().setDefault("font.regex.style", systemFont.getStyle());

+		getPreferenceStore().setDefault("font.searchtext.name", systemFont.getName());

+		getPreferenceStore().setDefault("font.searchtext.height", systemFont.getHeight());

+		getPreferenceStore().setDefault("font.searchtext.style", systemFont.getStyle());

+		getPreferenceStore().setDefault("font.result.name", systemFont.getName());

+		getPreferenceStore().setDefault("font.result.height", systemFont.getHeight());

+		getPreferenceStore().setDefault("font.result.style", systemFont.getStyle());

+	}

+

+	

+	public ImageDescriptor getImageDescriptor(String imageName) {

+		return imageDescriptorFromPlugin("org.eclipse.ui.regex", "icons/" + imageName);

+	}

+

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/ReplaceResult.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/ReplaceResult.java
new file mode 100644
index 0000000..20fb1dc
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/ReplaceResult.java
@@ -0,0 +1,39 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex;

+

+

+public class ReplaceResult {

+	

+	private Matches matches;

+	private String resultText;

+	

+	public ReplaceResult(String resultText, Matches matches) {

+		this.resultText = resultText;

+		this.matches = matches;

+		

+	}

+

+	/**

+	 * @return Returns the afterReplace.

+	 */

+	public String getResultText() {

+		return resultText;

+	}

+

+	/**

+	 * @return Returns the matches.

+	 */

+	public Matches getMatches() {

+		return matches;

+	}

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/IListener.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/IListener.java
new file mode 100644
index 0000000..7e22589
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/IListener.java
@@ -0,0 +1,17 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex.event;

+

+public interface IListener {

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/ListenerManager.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/ListenerManager.java
new file mode 100644
index 0000000..5a17976
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/event/ListenerManager.java
@@ -0,0 +1,34 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex.event;

+

+import java.util.ArrayList;

+import java.util.List;

+

+

+public abstract class ListenerManager {

+	

+	private List listeners = new ArrayList();

+	

+	public void addListener(IListener listener) {

+		listeners.add(listener);

+	}

+

+	public void removeListener(IListener listener) {

+		listeners.remove(listener);

+	}

+	

+	protected List getListeners() {

+	    return listeners;

+	}

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistKeyAdapter.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistKeyAdapter.java
new file mode 100644
index 0000000..475654c
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistKeyAdapter.java
@@ -0,0 +1,70 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.ArrayList;

+

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.custom.StyledText;

+import org.eclipse.swt.events.KeyAdapter;

+import org.eclipse.swt.events.KeyEvent;

+import org.eclipse.swt.graphics.Point;

+import org.eclipse.swt.graphics.Rectangle;

+

+

+public class AssistKeyAdapter extends KeyAdapter {

+

+	private StyledText textField;

+	

+	public void keyPressed(KeyEvent e) {

+		textField = (StyledText) e.widget;

+		int caretOffset = textField.getCaretOffset();

+

+		if (textField.getText().equals("") || caretOffset == 0) return;

+

+		String textSoFar = textField.getText(0, caretOffset - 1);

+

+		ArrayList proposals = Assistant.getAssistItems(textSoFar);

+				

+		if (proposals.size() != 0 && e.stateMask == SWT.CONTROL && e.keyCode == 32) {

+			Proposal proposal = showProposals(proposals);

+

+				if (proposal != null) {

+

+					textField.replaceTextRange(caretOffset

+							- proposal.getReplaceCount(), proposal

+							.getReplaceCount(), proposal

+							.getSubstitute());

+					textField.setCaretOffset(caretOffset

+							+ proposal.getSubstitute().length() - proposal.getReplaceCount());

+				} else {

+					textField.setCaretOffset(caretOffset);

+				}

+		

+				

+		} 

+	}

+	

+	protected Proposal showProposals(ArrayList proposals) {

+		AssistPopup assist = new AssistPopup(textField.getShell());

+		assist.setProposals(proposals);

+		Point pos = textField.toDisplay(textField.getCaret()

+				.getLocation());

+		return assist.open(new Rectangle(

+				pos.x + 10, pos.y - 90, 140, 120));

+		

+	}

+	

+

+

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistPopup.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistPopup.java
new file mode 100644
index 0000000..82bec58
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/AssistPopup.java
@@ -0,0 +1,182 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+

+import java.util.ArrayList;

+import java.util.Iterator;

+

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.events.ControlEvent;

+import org.eclipse.swt.events.ControlListener;

+import org.eclipse.swt.events.KeyEvent;

+import org.eclipse.swt.events.KeyListener;

+import org.eclipse.swt.events.MouseEvent;

+import org.eclipse.swt.events.MouseListener;

+import org.eclipse.swt.graphics.Color;

+import org.eclipse.swt.graphics.Point;

+import org.eclipse.swt.graphics.Rectangle;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.Event;

+import org.eclipse.swt.widgets.List;

+import org.eclipse.swt.widgets.Listener;

+import org.eclipse.swt.widgets.Shell;

+

+

+public class AssistPopup {

+	private Shell  shell;

+	private List   list;

+	private int    minimumWidth;

+	private ArrayList proposals;

+	private static final Color bgColor = new Color(Display.getCurrent(), 254, 241, 233);

+	

+public AssistPopup(Shell parent) {

+	this(parent, 0);

+}

+

+

+public AssistPopup(Shell parent, int style) {

+	shell = new Shell(parent, checkStyle(style));

+	

+	list = new List(shell, SWT.SINGLE | SWT.V_SCROLL);	

+	list.setBackground(bgColor);

+	

+	// close dialog if user selects outside of the shell

+	shell.addListener(SWT.Deactivate, new Listener() {

+		public void handleEvent(Event e){	

+			shell.setVisible (false);

+		}

+	});

+	

+	// resize shell when list resizes

+	shell.addControlListener(new ControlListener() {

+		public void controlMoved(ControlEvent e){}

+		public void controlResized(ControlEvent e){

+			Rectangle shellSize = shell.getClientArea();

+			list.setSize(shellSize.width, shellSize.height);

+		}

+	});

+	

+	// return list selection on Mouse Up or Carriage Return

+	list.addMouseListener(new MouseListener() {

+		public void mouseDoubleClick(MouseEvent e){}

+		public void mouseDown(MouseEvent e){}

+		public void mouseUp(MouseEvent e){

+			shell.setVisible (false);

+		}

+	});

+	list.addKeyListener(new KeyListener() {

+		public void keyReleased(KeyEvent e){}

+		public void keyPressed(KeyEvent e){

+			if (e.character == '\r'){

+				shell.setVisible (false);

+			}

+		}

+	});

+	

+}

+private static int checkStyle (int style) {

+	int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;

+	return style & mask;

+}

+

+

+public Proposal open (Rectangle rect) {

+

+	Point listSize = list.computeSize (rect.width, SWT.DEFAULT);

+	Rectangle screenSize = shell.getDisplay().getBounds();

+

+	// Position the dialog so that it does not run off the screen and the largest number of items are visible

+	int spaceBelow = screenSize.height - (rect.y + rect.height) - 30;

+	int spaceAbove = rect.y - 30;

+

+	int y = 0;

+	if (spaceAbove > spaceBelow && listSize.y > spaceBelow) {

+		// place popup list above table cell

+		if (listSize.y > spaceAbove){

+			listSize.y = spaceAbove;

+		} else {

+			listSize.y += 2;

+		}

+		y = rect.y - listSize.y;

+		

+	} else {

+		// place popup list below table cell

+		if (listSize.y > spaceBelow){

+			listSize.y = spaceBelow;

+		} else {

+			listSize.y += 2;

+		}

+		y = rect.y + rect.height;

+	}

+	

+	// Make dialog as wide as the cell

+	listSize.x = rect.width;

+	// dialog width should not be les than minimumwidth

+	if (listSize.x < minimumWidth)

+		listSize.x = minimumWidth;

+	

+	// Align right side of dialog with right side of cell

+	int x = rect.x + rect.width - listSize.x;

+	

+	shell.setBounds(x, y, listSize.x, listSize.y);

+	

+	shell.open();

+	list.setFocus();

+

+	Display display = shell.getDisplay();

+	while (!shell.isDisposed () && shell.isVisible ()) {

+		if (!display.readAndDispatch()) display.sleep();

+	}

+	

+	Proposal result = null;

+	if (!shell.isDisposed ()) {

+		if (list.getSelectionIndex() != -1) {

+			result = (Proposal) proposals.get(list.getSelectionIndex());

+		} 

+		shell.dispose();

+	}

+	return result;

+}

+

+

+public void select(String string) {

+	String[] items = list.getItems();

+

+	// find the first entry in the list that starts with the

+	// specified string

+	if (string != null){

+		for (int i = 0; i < items.length; i++) {

+			if (items[i].startsWith(string)){

+				int index = list.indexOf(items[i]);

+				list.select(index);

+				break;

+			}

+		}

+	}

+}

+

+public void setProposals(ArrayList proposals) {

+	this.proposals = proposals;

+	int c = 0;

+	String[] items = new String[proposals.size()];

+	for (Iterator i = proposals.iterator(); i.hasNext(); ) {

+		Proposal proposal = (Proposal) i.next();

+		items[c++] = proposal.getDescription();

+	}

+	list.setItems(items);

+}

+

+

+}

+

+

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Assistant.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Assistant.java
new file mode 100644
index 0000000..05c556c
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Assistant.java
@@ -0,0 +1,63 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.ArrayList;

+

+

+public class Assistant {

+

+

+	public static ArrayList getAssistItems(String textLeftOfCursor) {

+		ArrayList proposals = new ArrayList();

+		if (textLeftOfCursor.endsWith("\\")) {

+			proposals.add(new Proposal("\\A", "Beginning input \\A", 1));

+			proposals.add(new Proposal("\\b", "Word boundary \\b", 1));

+			proposals.add(new Proposal("\\B", "Non-word boundary \\B", 1));

+			proposals.add(new Proposal("\\d", "Digit \\d", 1));

+			proposals.add(new Proposal("\\D", "Non-digit \\D", 1));

+			proposals

+					.add(new Proposal("\\G", "End of previous match \\G", 1));

+			proposals.add(new Proposal("\\n", "Newline \\n", 1));

+			proposals.add(new Proposal("\\r", "Carriage-return \\r", 1));

+			proposals.add(new Proposal("\\s", "Whitespace \\s", 1));

+			proposals.add(new Proposal("\\S", "Non-whitespace \\S", 1));

+			proposals.add(new Proposal("\\t", "Tab \\t", 1));

+			proposals.add(new Proposal("\\w", "Word \\w", 1));

+			proposals.add(new Proposal("\\W", "Non-word \\W", 1));

+			proposals.add(new Proposal("\\z", "End of input \\z", 1));

+

+		}

+

+		if (textLeftOfCursor.endsWith("(?")) {

+			proposals.add(new Proposal("(?:", "Non-capturing group (?:", 2));

+			proposals.add(new Proposal("(?=", "Positive lookahead (?=", 2));

+			proposals.add(new Proposal("(?!", "Negative lookahead (?!", 2));

+			proposals

+					.add(new Proposal("(?<=", "Positive lookbehind (?<=", 2));

+			proposals

+					.add(new Proposal("(?<!", "Negative lookbehind (?<!", 2));

+

+		}

+

+		if (textLeftOfCursor.endsWith("[")) {

+			proposals.add(new Proposal("[0-9]", "[0-9]", 1));

+			proposals.add(new Proposal("[a-z]", "[a-z]", 1));

+			proposals.add(new Proposal("[A-Z]", "[A-Z]", 1));

+			proposals.add(new Proposal("[a-zA-Z]", "[a-zA-Z]", 1));

+			proposals.add(new Proposal("[a-zA-Z0-9]", "[a-zA-Z0-9]", 1));

+		}

+		

+		return proposals;

+	}

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/BracketMatchingKeyAdapter.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/BracketMatchingKeyAdapter.java
new file mode 100644
index 0000000..b7e24aa
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/BracketMatchingKeyAdapter.java
@@ -0,0 +1,145 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.custom.StyleRange;

+import org.eclipse.swt.custom.StyledText;

+import org.eclipse.swt.events.KeyAdapter;

+import org.eclipse.swt.events.KeyEvent;

+import org.eclipse.swt.widgets.Display;

+

+public class BracketMatchingKeyAdapter extends KeyAdapter {

+

+	public void keyPressed(KeyEvent e) {

+		StyledText txt_RegExp = (StyledText) e.widget;

+		txt_RegExp.setStyleRange(null);

+		

+		if (matchableBracket(e.character)) { 

+			

+			markMatchingBracket(txt_RegExp, e.character);

+

+		} else {

+				

+			final int KEY_LEFT_ARROW = 16777219;

+			final int KEY_RIGHT_ARROW = 16777220;

+	

+			if (e.keyCode == KEY_LEFT_ARROW || e.keyCode == KEY_RIGHT_ARROW) {

+			

+				int caretOffset = txt_RegExp.getCaretOffset();

+				String lastText = " ";

+				if (caretOffset - 1 >= 0) {

+					lastText = txt_RegExp.getText(caretOffset - 1, caretOffset - 1);

+				}

+		

+				if (matchableBracket(lastText.charAt(0))) {

+					markMatchingBracket(txt_RegExp, lastText.charAt(0));

+				}

+			

+			}

+		

+		}

+

+	}

+

+	protected void markMatchingBracket(StyledText txt_RegExp, char bracket) {

+		int caretOffset = txt_RegExp.getCaretOffset();

+		int brakePos = -1;

+		int ignoreInnerBracket = 0;

+		

+		if (isClosingBracket(bracket)) {

+			String text = txt_RegExp.getText(0, caretOffset - 1);

+			for (int i = text.length() - 2; i >= 0; i--) {

+				if (text.charAt(i) == bracket) {

+					ignoreInnerBracket++;

+				}

+				if (text.charAt(i) == getMatchingBracket(bracket)) {

+					if (ignoreInnerBracket == 0) {

+						brakePos = i;

+						break;

+					} else {

+						ignoreInnerBracket--;

+					}

+				}

+			}

+		}

+			

+		if (isOpeningBracket(bracket)) {

+			if (caretOffset != txt_RegExp.getText().length()) {

+				String text = txt_RegExp.getText(caretOffset, txt_RegExp.getText().length() - 1);

+				for (int i = 0; i < text.length(); i++) {

+					if (text.charAt(i) == bracket) {

+						ignoreInnerBracket++;

+					}

+					if (text.charAt(i) == getMatchingBracket(bracket)) {

+						if (ignoreInnerBracket == 0) {

+							brakePos = caretOffset + i;

+							break;

+						} else {

+							ignoreInnerBracket--;

+						}

+					}

+				}

+			}

+		}		

+		

+		if (brakePos != -1) {

+			StyleRange styleRange1 = new StyleRange(brakePos, 1, Display

+					.getCurrent().getSystemColor(SWT.COLOR_RED), Display

+					.getCurrent().getSystemColor(SWT.COLOR_WHITE), SWT.BOLD);

+			StyleRange styleRange2 = new StyleRange(caretOffset - 1, 1, Display

+					.getCurrent().getSystemColor(SWT.COLOR_RED), Display

+					.getCurrent().getSystemColor(SWT.COLOR_WHITE), SWT.BOLD);

+			

+			if (isOpeningBracket(bracket)) {

+				txt_RegExp

+					.setStyleRanges(new StyleRange[]{styleRange2, styleRange1});

+			}

+			if (isClosingBracket(bracket)) {

+				txt_RegExp

+					.setStyleRanges(new StyleRange[]{styleRange1, styleRange2});

+			}

+		}

+	}

+	

+	protected boolean matchableBracket(char bracket) {

+		if (bracket == ')' || bracket == ']' || bracket == '(' || bracket == '[' || bracket == '}' || bracket == '{') {

+			return true;

+		} else  {

+			return false;

+		}

+	}

+	

+	protected char getMatchingBracket(char bracket) {

+		if (bracket == ')') return '(';

+		if (bracket == '(') return ')';

+		if (bracket == ']') return '[';

+		if (bracket == '[') return ']';

+		if (bracket == '}') return '{';

+		if (bracket == '{') return '}';

+		return ' ';

+	}

+	

+	protected boolean isOpeningBracket(char bracket) {

+		if (bracket == '(') return true;

+		if (bracket == '[') return true;

+		if (bracket == '{') return true;

+		return false;	

+	}

+	

+	protected boolean isClosingBracket(char bracket) {

+		if (bracket == ')') return true;

+		if (bracket == ']') return true;

+		if (bracket == '}') return true;

+		return false;	

+	}

+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/CopyDeclarationAdapter.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/CopyDeclarationAdapter.java
new file mode 100644
index 0000000..46697ca
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/CopyDeclarationAdapter.java
@@ -0,0 +1,38 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import org.eclipse.swt.dnd.Clipboard;

+import org.eclipse.swt.dnd.TextTransfer;

+import org.eclipse.swt.dnd.Transfer;

+import org.eclipse.swt.events.SelectionAdapter;

+import org.eclipse.swt.events.SelectionEvent;

+import org.eclipse.ui.regex.RegExModel;

+

+

+public class CopyDeclarationAdapter extends SelectionAdapter {

+

+	public void widgetSelected(SelectionEvent e) {

+		String text = "Pattern.compile(\"" + RegExModel.getInstance().getRegExAsLiteral();

+		if (RegExModel.getInstance().getPatternFlags() == 0)

+			text += "\");";

+		else

+			text += "\"," + RegExModel.getInstance().getPatternFlagsAsString() + ");";

+		Clipboard clipboard = new Clipboard(e.display);

+		TextTransfer textTransfer = TextTransfer.getInstance();

+		clipboard.setContents(new Object[]{text},

+				new Transfer[]{textTransfer});

+		clipboard.dispose();

+

+	}

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Expression.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Expression.java
new file mode 100644
index 0000000..171ecc6
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Expression.java
@@ -0,0 +1,101 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+

+public class Expression {

+

+    private String regex = "";

+

+    private String searchText = "";

+

+    private String name = "";

+

+    private int matchMode = 0;

+

+    private int patternFlag = 0;

+    

+

+    public Expression(String name) {

+        this.name = name;

+    }

+

+    /**

+     * @param name The name to set.

+     */

+    public void setName(String name) {

+        this.name = name;

+    }

+    

+    /* (non-Javadoc)

+     * @see java.lang.Object#hashCode()

+     */

+    public int hashCode() {

+        int hash = 7;

+		hash = 31 * hash + (null == name ? 0 : name.hashCode());

+		return hash;

+    }

+    

+    /* (non-Javadoc)

+     * @see java.lang.Object#equals(java.lang.Object)

+     */

+    public boolean equals(Object o) {

+        if (o == this) return true;

+        if (o == null) return false;

+        if (! (o instanceof Expression)) return false;

+        Expression state = (Expression) o;

+        if (name.equals(state.getName())) {

+            	return true;

+        }              

+        return false;

+    }

+    

+    public String toString() {

+        return name;

+    }

+

+    public String getName() {

+        return name;

+    }

+

+    public int getMatchMode() {

+        return matchMode;

+    }

+

+    public void setMatchMode(int matchMode) {

+        this.matchMode = matchMode;

+    }

+

+    public int getPatternFlag() {

+        return patternFlag;

+    }

+

+    public void setPatternFlag(int patternFlag) {

+        this.patternFlag = patternFlag;

+    }

+

+    public String getRegex() {

+        return regex;

+    }

+

+    public void setRegex(String regex) {

+        this.regex = regex;

+    }

+

+    public String getSearchText() {

+        return searchText;

+    }

+

+    public void setSearchText(String searchText) {

+        this.searchText = searchText;

+    }

+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ExpressionLoader.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ExpressionLoader.java
new file mode 100644
index 0000000..22e4f74
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ExpressionLoader.java
@@ -0,0 +1,57 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.ArrayList;

+import java.util.Iterator;

+import java.util.List;

+

+

+public class ExpressionLoader {

+

+    private List listener = new ArrayList();

+    

+    private static ExpressionLoader instance;

+    

+    public static ExpressionLoader getInstance() {

+        if (instance == null) {

+            instance = new ExpressionLoader();

+        }

+        return instance;

+    }

+    

+    private ExpressionLoader() {}

+    

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.regex.view.IExpressionLoader#addExpressionLoaderListener(org.eclipse.ui.regex.view.IExpressionLoaderListener)

+     */

+    public void addExpressionLoaderListener(IExpressionLoaderListener loaderListener) {

+        listener.add(loaderListener);        

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.regex.view.IExpressionLoader#removeExpressionLoaderListener(org.eclipse.ui.regex.view.IExpressionLoaderListener)

+     */

+    public void removeExpressionLoaderListener(IExpressionLoaderListener loaderListener) {

+        listener.remove(loaderListener);    

+    }

+

+    

+    public void fireLoadExpression(Expression expression) {

+        for (Iterator i = listener.iterator(); i.hasNext();) {

+            IExpressionLoaderListener l = (IExpressionLoaderListener) i.next();

+            l.loadExpression(expression);

+        }

+    }

+    

+    

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/FontPreferencePage.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/FontPreferencePage.java
new file mode 100644
index 0000000..19daffb
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/FontPreferencePage.java
@@ -0,0 +1,227 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import org.eclipse.jface.preference.PreferencePage;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.events.SelectionEvent;

+import org.eclipse.swt.events.SelectionListener;

+import org.eclipse.swt.graphics.Font;

+import org.eclipse.swt.graphics.FontData;

+import org.eclipse.swt.layout.GridData;

+import org.eclipse.swt.layout.GridLayout;

+import org.eclipse.swt.widgets.Button;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.FontDialog;

+import org.eclipse.swt.widgets.Label;

+import org.eclipse.swt.widgets.Text;

+import org.eclipse.ui.IWorkbench;

+import org.eclipse.ui.IWorkbenchPreferencePage;

+import org.eclipse.ui.regex.RegExPlugin;

+

+

+public class FontPreferencePage extends PreferencePage implements IWorkbenchPreferencePage, SelectionListener {

+

+    private Button regexFontButton;

+    private Text regexFontText;

+    private FontData regexFontData;

+    private Text searchTextFontText;

+    private Button searchTextFontButton;

+    private Text resultFontText;

+    private Button resultFontButton;

+    private FontData searchTextFontData;

+    private FontData resultFontData;

+    

+    /* (non-Javadoc)

+     * @see org.eclipse.jface.preference.PreferencePage#performDefaults()

+     */

+    protected void performDefaults() {

+        String fontName   = getPreferenceStore().getDefaultString("font.regex.name");

+        int fontHeight = getPreferenceStore().getDefaultInt("font.regex.height");

+        int fontStyle  = getPreferenceStore().getDefaultInt("font.regex.style");

+        regexFontData = new FontData(fontName, fontHeight, fontStyle);

+        regexFontText.setText(buildDescription(fontName, fontHeight));

+    }

+    

+    private void setFontData() {

+        if (regexFontData != null) {

+			getPreferenceStore().setValue("font.regex.name", regexFontData.getName());

+			getPreferenceStore().setValue("font.regex.height", regexFontData.getHeight());

+			getPreferenceStore().setValue("font.regex.style", regexFontData.getStyle());

+        }

+        if (searchTextFontData != null) {

+			getPreferenceStore().setValue("font.searchtext.name", searchTextFontData.getName());

+			getPreferenceStore().setValue("font.searchtext.height", searchTextFontData.getHeight());

+			getPreferenceStore().setValue("font.searchtext.style", searchTextFontData.getStyle());

+        }

+        if (resultFontData != null) {

+			getPreferenceStore().setValue("font.result.name", resultFontData.getName());

+			getPreferenceStore().setValue("font.result.height", resultFontData.getHeight());

+			getPreferenceStore().setValue("font.result.style", resultFontData.getStyle());

+        }        

+    }

+    

+    /* (non-Javadoc)

+     * @see org.eclipse.jface.preference.PreferencePage#performApply()

+     */

+    protected void performApply() {

+        setFontData();

+    }

+    

+	/* (non-Javadoc)

+     * @see org.eclipse.jface.preference.IPreferencePage#performOk()

+     */

+    public boolean performOk() {

+        setFontData();

+		RegExPlugin.getDefault().savePluginPreferences();

+		return true;

+    }

+    

+    

+    /* (non-Javadoc)

+     * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)

+     */

+    protected Control createContents(Composite parent) {

+        Composite composite = new Composite(parent, SWT.NONE);

+        

+        GridLayout gridLayout = new GridLayout();

+        gridLayout.numColumns = 2;

+        composite.setLayout(gridLayout);

+        composite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH));

+        

+        Label regexFontLabel = new Label(composite, SWT.NONE);

+        regexFontLabel.setText("Regular Expression Font:");

+        GridData gridData = new GridData();

+        gridData.horizontalSpan = 2;

+        regexFontLabel.setLayoutData(gridData);

+        

+        regexFontText = new Text(composite, SWT.BORDER);

+        regexFontText.setText(buildDescription(fontName("regex"), fontHeight("regex")));

+        regexFontText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

+        regexFontText.setFont(createFont("regex"));

+        

+        regexFontButton = new Button(composite, SWT.PUSH);

+        regexFontButton.setText("Change...");

+        regexFontButton.addSelectionListener(this);

+        regexFontButton.setData("regex");

+        regexFontButton.setLayoutData(new GridData());

+

+        Label searchTextFontLabel = new Label(composite, SWT.NONE);

+        searchTextFontLabel.setText("Search Text Font:");

+        gridData = new GridData();

+        gridData.horizontalSpan = 2;

+        searchTextFontLabel.setLayoutData(gridData);

+        

+        searchTextFontText = new Text(composite, SWT.BORDER);

+        searchTextFontText.setText(buildDescription(fontName("searchtext"), fontHeight("searchtext")));

+        searchTextFontText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

+        searchTextFontText.setFont(createFont("searchtext"));

+        

+        searchTextFontButton = new Button(composite, SWT.PUSH);

+        searchTextFontButton.setText("Change...");

+        searchTextFontButton.addSelectionListener(this);

+        searchTextFontButton.setData("searchtext");

+        searchTextFontButton.setLayoutData(new GridData());

+

+        Label resultFontLabel = new Label(composite, SWT.NONE);

+        resultFontLabel.setText("Result Font:");

+        gridData = new GridData();

+        gridData.horizontalSpan = 2;

+        resultFontLabel.setLayoutData(gridData);

+        

+        resultFontText = new Text(composite, SWT.BORDER);

+        resultFontText.setText(buildDescription(fontName("result"), fontHeight("result")));

+        resultFontText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

+        resultFontText.setFont(createFont("result"));

+        

+        resultFontButton = new Button(composite, SWT.PUSH);

+        resultFontButton.setText("Change...");

+        resultFontButton.addSelectionListener(this);

+        resultFontButton.setData("result");

+        resultFontButton.setLayoutData(new GridData());       

+        

+        return parent;

+    }

+    

+    private String fontName(String type) {

+        return getPreferenceStore().getString("font." + type + ".name");

+    }

+

+    private int fontHeight(String type) {

+        return getPreferenceStore().getInt("font." + type + ".height");

+    }

+

+    private int fontStyle(String type) {

+        return getPreferenceStore().getInt("font." + type + ".style");

+    }

+    

+    private FontData fontData(String type) {

+        return new FontData(fontName(type), fontHeight(type), fontStyle(type));

+    }

+    

+    private Font createFont(String type) {

+        return new Font(Display.getCurrent(), fontData(type));

+    }

+    

+

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)

+     */

+    public void init(IWorkbench workbench) {

+        this.setPreferenceStore(RegExPlugin.getDefault().getPreferenceStore());

+        

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)

+     */

+    public void widgetSelected(SelectionEvent e) {

+        if (e.widget == regexFontButton || e.widget == searchTextFontButton || e.widget == resultFontButton) {

+            FontDialog fontDialog = new FontDialog(getShell());

+            fontDialog.setFontList(new FontData[]{fontData((String) ((Button) e.widget).getData())});

+            FontData fontData = fontDialog.open();

+            if (fontData != null) {

+                if (e.widget == regexFontButton) {

+	                regexFontData = fontData;

+	                regexFontText.setText(fontData.getName() + ", " + fontData.getHeight());

+	                regexFontText.setFont(new Font(Display.getCurrent(), fontData));

+                }

+                if (e.widget == searchTextFontButton) {

+	                searchTextFontData = fontData;

+	                searchTextFontText.setText(fontData.getName() + ", " + fontData.getHeight());

+	                searchTextFontText.setFont(new Font(Display.getCurrent(), fontData));

+                }

+                if (e.widget == resultFontButton) {

+	                resultFontData = fontData;

+	                resultFontText.setText(fontData.getName() + ", " + fontData.getHeight());

+	                resultFontText.setFont(new Font(Display.getCurrent(), fontData));

+                }

+            }

+        }

+        

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)

+     */

+    public void widgetDefaultSelected(SelectionEvent e) {

+        // TODO Auto-generated method stub

+        

+    }

+

+    private String buildDescription(String fontName, int fontHeight) {

+        return fontName + ", " + fontHeight;

+    }

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/IExpressionLoaderListener.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/IExpressionLoaderListener.java
new file mode 100644
index 0000000..e7551e2
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/IExpressionLoaderListener.java
@@ -0,0 +1,19 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+

+public interface IExpressionLoaderListener {

+    

+    public void loadExpression(Expression expression);

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ILiveEvalListener.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ILiveEvalListener.java
new file mode 100644
index 0000000..447d203
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/ILiveEvalListener.java
@@ -0,0 +1,25 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex.view;

+

+import org.eclipse.ui.regex.event.IListener;

+

+

+public interface ILiveEvalListener extends IListener {

+	

+	public void evalActivated();

+	public void evalDeactivated();

+	public void evalDone();

+	public void doEval();

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEval.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEval.java
new file mode 100644
index 0000000..dfbbc51
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEval.java
@@ -0,0 +1,124 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.swt.custom.ExtendedModifyEvent;

+import org.eclipse.swt.custom.ExtendedModifyListener;

+import org.eclipse.swt.custom.StyledText;

+import org.eclipse.ui.regex.RegExPlugin;

+

+public class LiveEval {

+	

+	private LiveEvalListenerManager liveEvalListenerManager;

+

+    class LiveEvalListener implements ExtendedModifyListener {

+

+        public void modifyText(ExtendedModifyEvent event) {

+            if (LiveEval.this.isLiveEval()) LiveEval.this.doEval();

+        }

+    }

+

+   

+    private boolean isLiveEval;

+

+    private LiveEvalListener liveEvalListener;

+

+    private StyledText regEx, searchText;

+

+    private IPreferenceStore prefs = RegExPlugin.getDefault()

+            .getPreferenceStore();

+

+    

+    public LiveEval(StyledText regEx, StyledText searchText) {

+        liveEvalListener = new LiveEvalListener();

+        this.regEx = regEx;

+        this.searchText = searchText;

+        isLiveEval = prefs.getBoolean("EvalSwitch");

+    

+        prefs.addPropertyChangeListener(new IPropertyChangeListener() {

+

+            public void propertyChange(PropertyChangeEvent event) {

+                if (LiveEval.this.regEx.isDisposed()

+                        || LiveEval.this.searchText.isDisposed()) { return; }

+                String prop = event.getProperty();

+

+                if (prop.equals("EvalSwitch")) {

+                    boolean newVal = ((Boolean) event.getNewValue())

+                            .booleanValue();

+                    if (newVal)

+                        LiveEval.this.start();

+                    else

+                        LiveEval.this.stop();

+                }

+                if (LiveEval.this.isLiveEval()) updateChangeListeners();

+            }

+        });

+        liveEvalListenerManager = new LiveEvalListenerManager();

+    }

+

+    public void addLiveEvalListener(ILiveEvalListener listener) {

+    	liveEvalListenerManager.addListener(listener);

+    }

+

+    public void removeLiveEvalListener(ILiveEvalListener listener) {

+    	liveEvalListenerManager.removeListener(listener);

+    }

+    

+    public boolean isLiveEval() {

+        return this.isLiveEval;

+    }

+

+    public void start() {

+        this.isLiveEval = true;

+        updateChangeListeners();

+        liveEvalListenerManager.publishEvalActivated();

+    }

+

+    public void stop() {

+        this.isLiveEval = false;

+        removeChangeListeners();

+        liveEvalListenerManager.publishEvalDeactivated();

+    }

+    

+

+  

+    private void doEval() {

+    	liveEvalListenerManager.publishDoEval();

+    	liveEvalListenerManager.publishEvalDone();

+    }

+

+    private void removeChangeListeners() {

+        regEx.removeExtendedModifyListener(liveEvalListener);

+        searchText.removeExtendedModifyListener(liveEvalListener);

+

+    }

+    

+    private void updateChangeListeners() {

+        removeChangeListeners();

+        if (prefs.getBoolean("EvalSearch")) {

+            searchText.addExtendedModifyListener(liveEvalListener);

+        }

+        if (prefs.getBoolean("EvalRegEx")) {

+            regEx.addExtendedModifyListener(liveEvalListener);

+        }

+        if (prefs.getBoolean("EvalBoth")) {

+            searchText.addExtendedModifyListener(liveEvalListener);

+            regEx.addExtendedModifyListener(liveEvalListener);

+        }

+    }

+

+    

+    

+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEvalListenerManager.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEvalListenerManager.java
new file mode 100644
index 0000000..6c52311
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/LiveEvalListenerManager.java
@@ -0,0 +1,50 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.Iterator;

+

+import org.eclipse.ui.regex.event.ListenerManager;

+

+

+public class LiveEvalListenerManager extends ListenerManager {

+

+	public void publishEvalActivated() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			ILiveEvalListener listener = (ILiveEvalListener) i.next();

+			listener.evalActivated();

+		}

+		};

+		

+	public void publishEvalDeactivated() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			ILiveEvalListener listener = (ILiveEvalListener) i.next();

+			listener.evalDeactivated();

+		}

+		};

+		

+	public void publishEvalDone() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			ILiveEvalListener listener = (ILiveEvalListener) i.next();

+			listener.evalDone();

+		}

+		};

+		

+	public void publishDoEval() {

+		for (Iterator i = getListeners().iterator(); i.hasNext(); ) {

+			ILiveEvalListener listener = (ILiveEvalListener) i.next();

+			listener.doEval();

+		}

+		};

+		

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Proposal.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Proposal.java
new file mode 100644
index 0000000..36a2cc3
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/Proposal.java
@@ -0,0 +1,69 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+public class Proposal {

+

+	private String substitute;

+	private String description;

+	private int replaceCount;

+	

+	/**

+	 * @param substitute

+	 * @param description

+	 */

+	public Proposal(String substitute, String description, int replaceCount) {

+		super();

+		this.substitute = substitute;

+		this.description = description;

+		this.replaceCount = replaceCount;

+	}

+

+

+

+	/**

+	 * @return Returns the replaceCount.

+	 */

+	public int getReplaceCount() {

+		return replaceCount;

+	}

+	/**

+	 * @param replaceCount The replaceCount to set.

+	 */

+	public void setReplaceCount(int replaceCount) {

+		this.replaceCount = replaceCount;

+	}

+	/**

+	 * @return Returns the description.

+	 */

+	public String getDescription() {

+		return description;

+	}

+	/**

+	 * @param description The description to set.

+	 */

+	public void setDescription(String description) {

+		this.description = description;

+	}

+	/**

+	 * @return Returns the substitute.

+	 */

+	public String getSubstitute() {

+		return substitute;

+	}

+	/**

+	 * @param substitute The substitute to set.

+	 */

+	public void setSubstitute(String substitute) {

+		this.substitute = substitute;

+	}

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExPreferencePage.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExPreferencePage.java
new file mode 100644
index 0000000..6f34bc9
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExPreferencePage.java
@@ -0,0 +1,151 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.regex.Pattern;

+

+import org.eclipse.jface.preference.PreferencePage;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.layout.GridData;

+import org.eclipse.swt.layout.GridLayout;

+import org.eclipse.swt.widgets.Button;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.swt.widgets.Group;

+import org.eclipse.ui.IWorkbench;

+import org.eclipse.ui.IWorkbenchPreferencePage;

+import org.eclipse.ui.regex.RegExPlugin;

+

+

+public class RegExPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

+

+	private Button btn_CanonicalEquivalence;

+	private Button btn_CaseInsensitive;

+	private Button btn_Comments;

+	private Button btn_DotallMode;

+	private Button btn_MultilineMode;

+	private Button btn_UnicodeCase;

+	private Button btn_UnixLines;

+	private Button btn_EvalRegEx;

+	private Button btn_EvalSearch;

+	private Button btn_EvalBoth;

+	private Button btn_EvalSwitch;

+	

+	public RegExPreferencePage() {

+	}

+

+

+	public void init(IWorkbench workbench)  {

+		this.setPreferenceStore(RegExPlugin.getDefault().getPreferenceStore());

+	}

+

+	protected void performDefaults() {

+		btn_CanonicalEquivalence.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.CANON_EQ"));

+		btn_CaseInsensitive.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.CASE_INSENSITIVE"));

+		btn_Comments.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.COMMENTS"));

+		btn_DotallMode.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.DOTALL"));

+		btn_MultilineMode.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.MULTILINE"));

+		btn_UnicodeCase.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.UNICODE_CASE"));

+		btn_UnixLines.setSelection(getPreferenceStore().getDefaultBoolean("Pattern.UNIX_LINES"));

+		btn_EvalRegEx.setSelection(getPreferenceStore().getDefaultBoolean("EvalRegEx"));

+		btn_EvalSearch.setSelection(getPreferenceStore().getDefaultBoolean("EvalSearch"));

+		btn_EvalBoth.setSelection(getPreferenceStore().getDefaultBoolean("EvalBoth"));

+		btn_EvalSwitch.setSelection(getPreferenceStore().getDefaultBoolean("EvalSwitch"));

+	}

+	

+	public boolean performOk() {

+		getPreferenceStore().setValue("Pattern.CANON_EQ",btn_CanonicalEquivalence.getSelection());

+		getPreferenceStore().setValue("Pattern.CASE_INSENSITIVE",btn_CaseInsensitive.getSelection());

+		getPreferenceStore().setValue("Pattern.COMMENTS",btn_Comments.getSelection());

+		getPreferenceStore().setValue("Pattern.DOTALL",btn_DotallMode.getSelection());

+		getPreferenceStore().setValue("Pattern.MULTILINE",btn_MultilineMode.getSelection());

+		getPreferenceStore().setValue("Pattern.UNICODE_CASE",btn_UnicodeCase.getSelection());

+		getPreferenceStore().setValue("Pattern.UNIX_LINES",btn_UnixLines.getSelection());

+		getPreferenceStore().setValue("EvalRegEx",btn_EvalRegEx.getSelection());

+		getPreferenceStore().setValue("EvalSearch",btn_EvalSearch.getSelection());

+		getPreferenceStore().setValue("EvalBoth",btn_EvalBoth.getSelection());

+		getPreferenceStore().setValue("EvalSwitch",btn_EvalSwitch.getSelection());		

+		RegExPlugin.getDefault().savePluginPreferences();

+		return true;

+	}

+

+	protected Control createContents(Composite parent)  {

+

+		Group group=new Group(parent,SWT.SHADOW_ETCHED_IN);

+		group.setText("Default Pattern Flags");

+		GridLayout groupGridLayout=new GridLayout();

+		groupGridLayout.numColumns=2;

+		

+		group.setLayout(groupGridLayout);

+		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));

+		

+		btn_CanonicalEquivalence=new Button(group,SWT.CHECK);

+		btn_CanonicalEquivalence.setText("Canonical &Equivalence");

+		btn_CanonicalEquivalence.setData(new Integer(Pattern.CANON_EQ));

+		btn_CanonicalEquivalence.setSelection(getPreferenceStore().getBoolean("Pattern.CANON_EQ"));

+		

+		btn_CaseInsensitive=new Button(group,SWT.CHECK);

+		btn_CaseInsensitive.setText("Case &Insensitive");

+		btn_CaseInsensitive.setData(new Integer(Pattern.CASE_INSENSITIVE));

+		btn_CaseInsensitive.setSelection(getPreferenceStore().getBoolean("Pattern.CASE_INSENSITIVE"));

+				

+		btn_Comments=new Button(group,SWT.CHECK);

+		btn_Comments.setText("&Comments");

+		btn_Comments.setData(new Integer(Pattern.COMMENTS));

+		btn_Comments.setSelection(getPreferenceStore().getBoolean("Pattern.COMMENTS"));

+					

+		btn_DotallMode=new Button(group,SWT.CHECK);

+		btn_DotallMode.setText("&Dotall Mode");

+		btn_DotallMode.setData(new Integer(Pattern.DOTALL));		

+		btn_DotallMode.setSelection(getPreferenceStore().getBoolean("Pattern.DOTALL"));

+				

+		btn_MultilineMode=new Button(group,SWT.CHECK);

+		btn_MultilineMode.setText("&Multiline Mode");

+		btn_MultilineMode.setData(new Integer(Pattern.MULTILINE));

+		btn_MultilineMode.setSelection(getPreferenceStore().getBoolean("Pattern.MULTILINE"));

+		

+		btn_UnicodeCase=new Button(group,SWT.CHECK);

+		btn_UnicodeCase.setText("&Unicode Case");

+		btn_UnicodeCase.setData(new Integer(Pattern.UNICODE_CASE));

+		btn_UnicodeCase.setSelection(getPreferenceStore().getBoolean("Pattern.UNICODE_CASE"));

+		

+		btn_UnixLines=new Button(group,SWT.CHECK);

+		btn_UnixLines.setText("Unix &Lines");

+		btn_UnixLines.setData(new Integer(Pattern.UNIX_LINES));

+		btn_UnixLines.setSelection(getPreferenceStore().getBoolean("Pattern.UNIX_LINES"));

+

+		Group evalGroup=new Group(parent,SWT.SHADOW_ETCHED_IN);

+		evalGroup.setText("Live Evaluation");

+		GridLayout evalGridLayout=new GridLayout();

+		evalGridLayout.numColumns=1;

+		evalGroup.setLayout(evalGridLayout);

+		evalGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));

+

+		btn_EvalRegEx=new Button(evalGroup,SWT.RADIO);

+		btn_EvalRegEx.setText("React On &Regular Expression Changes");

+		btn_EvalRegEx.setSelection(getPreferenceStore().getBoolean("EvalRegEx"));

+		

+		btn_EvalSearch=new Button(evalGroup,SWT.RADIO);

+		btn_EvalSearch.setText("React On &Search Text Changes");

+		btn_EvalSearch.setSelection(getPreferenceStore().getBoolean("EvalSearch"));

+				

+		btn_EvalBoth=new Button(evalGroup,SWT.RADIO);

+		btn_EvalBoth.setText("&React On Everything");

+		btn_EvalBoth.setSelection(getPreferenceStore().getBoolean("EvalBoth"));

+				

+		btn_EvalSwitch=new Button(evalGroup,SWT.CHECK);

+		btn_EvalSwitch.setText("Use Live &Evaluation");										

+		btn_EvalSwitch.setSelection(getPreferenceStore().getBoolean("EvalSwitch"));

+		

+		return null;

+	}

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExView.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExView.java
new file mode 100644
index 0000000..3cb84cd
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/RegExView.java
@@ -0,0 +1,864 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view;

+

+import java.util.Iterator;

+import java.util.regex.Matcher;

+import java.util.regex.Pattern;

+

+import org.eclipse.jface.action.IAction;

+import org.eclipse.jface.action.Separator;

+import org.eclipse.jface.dialogs.IInputValidator;

+import org.eclipse.jface.dialogs.InputDialog;

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.jface.window.Window;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.custom.SashForm;

+import org.eclipse.swt.custom.StyleRange;

+import org.eclipse.swt.custom.StyledText;

+import org.eclipse.swt.custom.VerifyKeyListener;

+import org.eclipse.swt.dnd.Clipboard;

+import org.eclipse.swt.dnd.TextTransfer;

+import org.eclipse.swt.dnd.Transfer;

+import org.eclipse.swt.events.FocusEvent;

+import org.eclipse.swt.events.FocusListener;

+import org.eclipse.swt.events.MenuEvent;

+import org.eclipse.swt.events.MenuListener;

+import org.eclipse.swt.events.SelectionAdapter;

+import org.eclipse.swt.events.SelectionEvent;

+import org.eclipse.swt.events.SelectionListener;

+import org.eclipse.swt.events.VerifyEvent;

+import org.eclipse.swt.graphics.Color;

+import org.eclipse.swt.graphics.Font;

+import org.eclipse.swt.graphics.FontData;

+import org.eclipse.swt.layout.GridData;

+import org.eclipse.swt.layout.GridLayout;

+import org.eclipse.swt.layout.RowLayout;

+import org.eclipse.swt.widgets.Button;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Display;

+import org.eclipse.swt.widgets.Label;

+import org.eclipse.swt.widgets.Menu;

+import org.eclipse.swt.widgets.MenuItem;

+import org.eclipse.swt.widgets.Widget;

+import org.eclipse.ui.part.ViewPart;

+import org.eclipse.ui.regex.Group;

+import org.eclipse.ui.regex.IRegExListener;

+import org.eclipse.ui.regex.Match;

+import org.eclipse.ui.regex.Matches;

+import org.eclipse.ui.regex.RegExModel;

+import org.eclipse.ui.regex.RegExPlugin;

+import org.eclipse.ui.regex.ReplaceResult;

+import org.eclipse.ui.regex.view.actions.AboutAction;

+import org.eclipse.ui.regex.view.actions.ClearAction;

+import org.eclipse.ui.regex.view.actions.NextMatchAction;

+import org.eclipse.ui.regex.view.actions.PrevMatchAction;

+import org.eclipse.ui.regex.view.actions.StandardTextFieldAction;

+import org.eclipse.ui.regex.view.actions.StyledTextActionHandler;

+

+

+public class RegExView extends ViewPart implements SelectionListener,

+        IRegExListener, ILiveEvalListener, IExpressionLoaderListener, IPropertyChangeListener {

+

+    private StyledText txt_RegExp;

+

+    private StyledText txt_SearchText;

+

+    private StyledText txt_Result;

+

+    private Label lbl_RegExp;

+

+    private Button btn_Find, btn_LiveEval;

+

+    private Composite cmp_ButtonGroup;

+

+    private MenuItem mit_CopyLiteral, mit_mReplace, mit_mFind, mit_mMatch,

+            mit_PasteLiteral, mit_mSplit, mit_EvalSelection;

+

+    private int currentCarresPos = 0;

+

+    private final RegExModel regex;

+

+    private LiveEval liveEval;

+

+    private IAction prevMatchAction;

+

+    private IAction nextMatchAction;

+

+    private IAction clearAction;

+

+    private IPreferenceStore prefs;

+    

+    private Menu men_PatternFlags;

+

+    private String[] modeLabels = new String[] { "Find", "Match", "Split", "Replace"};

+

+    private static final Color COLOR_WHITE = Display.getCurrent()

+            .getSystemColor(SWT.COLOR_WHITE);

+

+    private static final Color COLOR_RED = Display.getCurrent().getSystemColor(

+            SWT.COLOR_RED);

+

+    private Menu men_MatchMode;

+

+    private MenuItem mit_MatchMode;

+

+    private AboutAction aboutAction;

+

+    

+    public RegExView() {

+    

+        regex = RegExModel.getInstance();

+        prefs = RegExPlugin.getDefault().getPreferenceStore();

+        prefs.addPropertyChangeListener(this);

+        regex.addRegExListener(this);

+

+        ExpressionLoader.getInstance().addExpressionLoaderListener(this);

+       

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.IWorkbenchPart#dispose()

+     */

+    public void dispose() {

+        regex.removeRegExListener(this);

+        prefs.removePropertyChangeListener(this);

+        ExpressionLoader.getInstance().removeExpressionLoaderListener(this);

+    }

+    

+    

+    public void createPartControl(final Composite parent) {

+

+        makeActions();

+

+        GridLayout gridLayout = new GridLayout();

+        gridLayout.numColumns = 1;

+

+        parent.setLayout(gridLayout);

+        GridData gridData = new GridData();

+        parent.setLayoutData(gridData);

+

+        lbl_RegExp = new Label(parent, SWT.LEFT);

+        lbl_RegExp.setText("Regular Expression");

+

+        txt_RegExp = new StyledText(parent, SWT.LEFT | SWT.BORDER | SWT.SINGLE);

+

+      

+            txt_RegExp.addKeyListener(new BracketMatchingKeyAdapter());

+            txt_RegExp.addKeyListener(new AssistKeyAdapter());

+        

+

+        // GRO: Store/Restore last input value from PreferenceStore

+        IPreferenceStore preferenceStore = RegExPlugin.getDefault().getPreferenceStore();

+        String preferenceKey = "txt_RegExp";

+        txt_RegExp.addFocusListener(new SaveLastValueToPreferenceStoreFocusAdapter(preferenceStore, preferenceKey));

+        txt_RegExp.setText(preferenceStore.getString(preferenceKey));

+        

+        

+        txt_RegExp.addFocusListener(new FocusListener() {

+

+            private int caretOffset;

+

+            public void focusGained(FocusEvent e) {

+                ((StyledText) e.widget).setCaretOffset(caretOffset);

+            }

+

+            public void focusLost(FocusEvent e) {

+                caretOffset = ((StyledText) e.widget).getCaretOffset();

+            }

+        });

+

+        txt_RegExp.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.regex.name"), prefs.getInt("font.regex.height"), prefs.getInt("font.regex.style"))));

+        txt_RegExp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

+

+        txt_RegExp.setMenu(new Menu(parent.getShell()));

+        setTextMenuItems(txt_RegExp);

+        new MenuItem(txt_RegExp.getMenu(), SWT.BAR);

+        setPatternFlagMenu(txt_RegExp.getMenu());

+

+        txt_RegExp.getMenu().addMenuListener(new MenuListener() {

+

+               	

+            public void menuHidden(MenuEvent e) {

+     

+            }

+

+            public void menuShown(MenuEvent e) {

+                if (txt_RegExp.getSelectionCount() > 0) {

+                	mit_EvalSelection.setEnabled(true);

+                } else {

+                	mit_EvalSelection.setEnabled(false);

+                }

+

+            }

+        });

+

+        // RegEx Menu: Match Mode

+        

+            men_MatchMode = new Menu(txt_RegExp.getMenu());

+            mit_MatchMode = new MenuItem(txt_RegExp.getMenu(),

+                                SWT.CASCADE);

+            mit_MatchMode.setText("Match mode");

+            mit_MatchMode.setMenu(men_MatchMode);

+

+            mit_mFind = new MenuItem(men_MatchMode, SWT.RADIO);

+            mit_mFind.setText("Find sequence");

+            mit_mFind.setData(new Integer(RegExModel.MODE_FIND));

+            mit_mFind.setSelection(true);

+            mit_mFind.addSelectionListener(this);

+

+            mit_mMatch = new MenuItem(men_MatchMode, SWT.RADIO);

+            mit_mMatch.setText("Match complete text");

+            mit_mMatch.setData(new Integer(RegExModel.MODE_MATCH));

+            mit_mMatch.addSelectionListener(this);

+

+            mit_mSplit = new MenuItem(men_MatchMode, SWT.RADIO);

+            mit_mSplit.setText("Split");

+            mit_mSplit.setData(new Integer(RegExModel.MODE_SPLIT));

+            mit_mSplit.addSelectionListener(this);

+

+            mit_mReplace = new MenuItem(men_MatchMode, SWT.RADIO);

+            mit_mReplace.setText("Replace...");

+            mit_mReplace.setData(new Integer(RegExModel.MODE_REPLACE));

+            mit_mReplace.addSelectionListener(this);

+

+        

+

+        // RegEx Menu Item: Copy As String Literal

+        mit_CopyLiteral = new MenuItem(txt_RegExp.getMenu(), SWT.NONE);

+        mit_CopyLiteral.setText("Copy As String &Literal");

+        mit_CopyLiteral.addSelectionListener(this);

+

+        mit_PasteLiteral = new MenuItem(txt_RegExp.getMenu(), SWT.NONE);

+        mit_PasteLiteral.setText("&Paste String Literal");

+        mit_PasteLiteral.addSelectionListener(this);

+

+        

+        	new MenuItem(txt_RegExp.getMenu(), SWT.BAR);

+            mit_EvalSelection = new MenuItem(txt_RegExp.getMenu(), SWT.NONE);

+	        mit_EvalSelection.setText("Eval Selection Only");

+	        mit_EvalSelection.addSelectionListener(new SelectionListener() {

+	

+				public void widgetSelected(SelectionEvent e) {

+			        regex.setRegExp(txt_RegExp.getSelectionText());

+			        regex.setSearchText(txt_SearchText.getText());

+			        regex.process();

+					

+				}

+	

+				public void widgetDefaultSelected(SelectionEvent e) {

+					// TODO Auto-generated method stub

+					

+				}});

+        

+        

+        

+        SashForm sashForm = new SashForm(parent, SWT.VERTICAL);

+        sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));

+

+        txt_SearchText = new StyledText(sashForm, SWT.LEFT | SWT.MULTI

+                | SWT.V_SCROLL | SWT.BORDER);

+        txt_SearchText.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.searchtext.name"), prefs.getInt("font.searchtext.height"), prefs.getInt("font.searchtext.style"))));

+        txt_SearchText.setWordWrap(true);

+        txt_SearchText.setLayoutData(new GridData(GridData.FILL_BOTH));

+        txt_SearchText.addVerifyKeyListener(new VerifyKeyListener() {

+

+            public void verifyKey(VerifyEvent event) {

+                if (event.keyCode == SWT.TAB) {

+                    txt_RegExp.setCaretOffset(currentCarresPos);

+                    currentCarresPos = txt_SearchText.getCaretOffset();

+                    txt_RegExp.setFocus();

+                    event.doit = false;

+                }

+            }

+        });

+

+        txt_SearchText.setMenu(new Menu(parent.getShell()));

+        setTextMenuItems(txt_SearchText);

+        

+        

+        // GRO: Store/Restore last input value from PreferenceStore 

+        preferenceKey = "txt_SearchText";

+        txt_SearchText.addFocusListener(new SaveLastValueToPreferenceStoreFocusAdapter(preferenceStore, preferenceKey));

+        txt_SearchText.setText(preferenceStore.getString(preferenceKey));

+

+      

+

+        txt_Result = new StyledText(sashForm, SWT.LEFT | SWT.MULTI

+                | SWT.V_SCROLL | SWT.BORDER | SWT.READ_ONLY);

+

+        txt_Result.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.result.name"), prefs.getInt("font.result.height"), prefs.getInt("font.result.style"))));

+        txt_Result.setWordWrap(true);

+        txt_Result.setLayoutData(new GridData(GridData.FILL_BOTH));

+        txt_Result.setBackground(Display.getCurrent().getSystemColor(

+                SWT.COLOR_WIDGET_BACKGROUND));

+        txt_Result.setMenu(new Menu(parent.getShell()));

+        setTextMenuItems(txt_Result);

+

+        cmp_ButtonGroup = new Composite(parent, 0);

+        RowLayout buttonRow = new RowLayout();

+        buttonRow.pack = false;

+        buttonRow.marginLeft = 0;

+        buttonRow.spacing = 20;

+        cmp_ButtonGroup.setLayout(buttonRow);

+

+        btn_Find = new Button(cmp_ButtonGroup, SWT.CENTER | SWT.FLAT);

+        btn_Find.setText("&Find");

+        btn_Find.addSelectionListener(this);

+

+        liveEval = new LiveEval(txt_RegExp, txt_SearchText);

+        liveEval.addLiveEvalListener(this);

+

+        btn_LiveEval = new Button(cmp_ButtonGroup, SWT.CHECK | SWT.FLAT);

+        btn_LiveEval.setText("&Live Evaluation");

+        if (prefs.getBoolean("EvalSwitch")) {

+            btn_LiveEval.setSelection(true);

+            liveEval.start();

+        }

+

+        btn_LiveEval.addSelectionListener(new SelectionAdapter() {

+

+            public void widgetSelected(SelectionEvent e) {

+                Button check = (Button) e.widget;

+                if (check.getSelection()) {

+                    liveEval.start();

+                } else {

+                    liveEval.stop();

+                }

+            }

+        });

+

+        StyledTextActionHandler styledTextActionHandler = new StyledTextActionHandler(

+                this.getViewSite().getActionBars());

+        styledTextActionHandler.addStyledText(txt_RegExp);

+        styledTextActionHandler.addStyledText(txt_SearchText);

+        styledTextActionHandler.addStyledText(txt_Result);

+

+        if (liveEval.isLiveEval()) {

+            processRegEx();

+            updateFoundStatus();

+        }

+

+    }

+

+    public void updateFoundStatus() {

+        if (regex.foundMatches()) {

+            if (regex.getMatches().getMatchPos() > 0)

+                prevMatchAction.setEnabled(true);

+            else

+                prevMatchAction.setEnabled(false);

+

+            if (regex.getMatches().getMatchPos() < regex.getMatches()

+                    .getMatchCount() - 1)

+                nextMatchAction.setEnabled(true);

+            else

+                nextMatchAction.setEnabled(false);

+        } else {

+            prevMatchAction.setEnabled(false);

+            nextMatchAction.setEnabled(false);

+        }

+    }

+

+    private void makeActions() {

+        nextMatchAction = new NextMatchAction(this);

+        prevMatchAction = new PrevMatchAction(this);

+        clearAction = new ClearAction(this);

+        

+        

+        aboutAction = new AboutAction(this);

+		

+        getViewSite().getActionBars().getToolBarManager().add(clearAction);

+        getViewSite().getActionBars().getToolBarManager().add(new Separator());

+        getViewSite().getActionBars().getToolBarManager().add(prevMatchAction);

+        getViewSite().getActionBars().getToolBarManager().add(nextMatchAction);

+        //getViewSite().getActionBars().getMenuManager().add(registerAction);

+        getViewSite().getActionBars().getMenuManager().add(aboutAction);

+    }

+

+    public void selectNextMatch() {

+        Match match = regex.getMatches().nextMatch();

+        if (match != null) {

+            StyledText searchText = txt_SearchText;

+            StyledText resultText = txt_Result;

+            searchText.setSelection(match.getStart(), match.getEnd());

+

+            String resultStr = resultText.getText();

+            Pattern patt = Pattern.compile("start=" + match.getStart()

+                    + ", end=" + match.getEnd());

+            Matcher matcher = patt.matcher(resultStr);

+            if (matcher.find()) {

+                resultText.setSelection(matcher.start(), matcher.end());

+            }

+        }

+    }

+

+    public void selectPreviousMatch() {

+        Match match = regex.getMatches().prevMatch();

+

+        if (match != null) {

+            StyledText searchText = txt_SearchText;

+            StyledText resultText = txt_Result;

+            searchText.setSelection(match.getStart(), match.getEnd());

+            String resultStr = resultText.getText();

+

+            Pattern patt = Pattern.compile("start=" + match.getStart()

+                    + ", end=" + match.getEnd());

+            Matcher matcher = patt.matcher(resultStr);

+            if (matcher.find()) {

+                resultText.setSelection(matcher.start(), matcher.end());

+            }

+        }

+

+    }

+

+    public void clear(int mode) {

+

+        if (mode == ClearAction.MODE_REGEX || mode == ClearAction.MODE_ALL) {

+            txt_RegExp.setText("");

+        }

+        if (mode == ClearAction.MODE_SEARCH || mode == ClearAction.MODE_ALL) {

+            txt_SearchText.setText("");

+        }

+        if (mode == ClearAction.MODE_RESULT || mode == ClearAction.MODE_ALL) {

+            txt_Result.setText("");

+        }

+

+        regex.reset();

+

+    }

+

+    private void setPatternFlagMenu(Menu menu) {

+        class FlagStatusAdapter extends SelectionAdapter {

+

+            public void widgetSelected(SelectionEvent e) {

+                MenuItem menItem = (MenuItem) e.widget;

+                Integer flag = (Integer) menItem.getData();

+                if (menItem.getSelection()) {

+                    regex.addPatternFlag(flag.intValue());

+                } else {

+                    regex.removePatternFlag(flag.intValue());

+                }

+                if (liveEval.isLiveEval()) {

+                    processRegEx();

+                    updateFoundStatus();

+                }

+                txt_RegExp.setToolTipText(regex.getPatternFlagsAsString());

+            }

+        }

+        FlagStatusAdapter flagStatusAdapter = new FlagStatusAdapter();

+

+        men_PatternFlags = new Menu(menu);

+        MenuItem mit_PatternFlags = new MenuItem(menu, SWT.CASCADE);

+        mit_PatternFlags.setText("Pattern &Flags");

+        mit_PatternFlags.setMenu(men_PatternFlags);

+

+        MenuItem mit_Flags_CanonEq = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_CanonEq.setText("Canonical &Equivalence");

+        mit_Flags_CanonEq.setData(new Integer(Pattern.CANON_EQ));

+        mit_Flags_CanonEq.setSelection(prefs.getBoolean("Pattern.CANON_EQ"));

+        mit_Flags_CanonEq.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_CaseIns = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_CaseIns.setText("Case &Insensitive");

+        mit_Flags_CaseIns.setData(new Integer(Pattern.CASE_INSENSITIVE));

+        mit_Flags_CaseIns.setSelection(prefs

+                .getBoolean("Pattern.CASE_INSENSITIVE"));

+        mit_Flags_CaseIns.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_Comments = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_Comments.setText("&Comments");

+        mit_Flags_Comments.setData(new Integer(Pattern.COMMENTS));

+        mit_Flags_Comments.setSelection(prefs.getBoolean("Pattern.COMMENTS"));

+        mit_Flags_Comments.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_Dotall = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_Dotall.setText("&Dotall Mode");

+        mit_Flags_Dotall.setData(new Integer(Pattern.DOTALL));

+        mit_Flags_Dotall.setSelection(prefs.getBoolean("Pattern.DOTALL"));

+        mit_Flags_Dotall.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_Multiline = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_Multiline.setText("&Multiline Mode");

+        mit_Flags_Multiline.setData(new Integer(Pattern.MULTILINE));

+        mit_Flags_Multiline.setSelection(prefs.getBoolean("Pattern.MULTILINE"));

+        mit_Flags_Multiline.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_unicodeCase = new MenuItem(men_PatternFlags,

+                SWT.CHECK);

+        mit_Flags_unicodeCase.setText("&Unicode Case");

+        mit_Flags_unicodeCase.setData(new Integer(Pattern.UNICODE_CASE));

+        mit_Flags_unicodeCase.setSelection(prefs

+                .getBoolean("Pattern.UNICODE_CASE"));

+        mit_Flags_unicodeCase.addSelectionListener(flagStatusAdapter);

+

+        MenuItem mit_Flags_unixLines = new MenuItem(men_PatternFlags, SWT.CHECK);

+        mit_Flags_unixLines.setText("Unix &Lines");

+        mit_Flags_unixLines.setData(new Integer(Pattern.UNIX_LINES));

+        mit_Flags_unixLines

+                .setSelection(prefs.getBoolean("Pattern.UNIX_LINES"));

+        mit_Flags_unixLines.addSelectionListener(flagStatusAdapter);

+

+        new MenuItem(men_PatternFlags, SWT.BAR);

+        MenuItem mit_Flags_deactivateAll = new MenuItem(men_PatternFlags,

+                SWT.NONE);

+        mit_Flags_deactivateAll.setText("Deactivate &All");

+        mit_Flags_deactivateAll.addSelectionListener(new SelectionAdapter() {

+

+            public void widgetSelected(SelectionEvent e) {

+                MenuItem menItem = (MenuItem) e.widget;

+                Menu menu = menItem.getParent();

+                MenuItem[] menItems = menu.getItems();

+                for (int i = 0; i < menItems.length; i++) {

+                    menItems[i].setSelection(false);

+                }

+                regex.resetPatternFlag();

+            }

+        });

+

+    }

+

+    public void setFocus() {

+        txt_RegExp.setFocus();

+    }

+

+    private void setTextMenuItems(StyledText text) {

+        MenuItem mitCut = new MenuItem(text.getMenu(), SWT.NONE);

+        mitCut.setText("Cu&t");

+        mitCut.setData(new StandardTextFieldAction(text,

+                StandardTextFieldAction.CUT));

+        mitCut.addSelectionListener(this);

+

+        MenuItem mitCopy = new MenuItem(text.getMenu(), SWT.NONE);

+        mitCopy.setText("&Copy");

+        mitCopy.setData(new StandardTextFieldAction(text,

+                StandardTextFieldAction.COPY));

+        mitCopy.addSelectionListener(this);

+

+        MenuItem mitPaste = new MenuItem(text.getMenu(), SWT.NONE);

+        mitPaste.setText("&Paste");

+        mitPaste.setData(new StandardTextFieldAction(text,

+                StandardTextFieldAction.PASTE));

+        mitPaste.addSelectionListener(this);

+

+        MenuItem mitSelectAll = new MenuItem(text.getMenu(), SWT.NONE);

+        mitSelectAll.setText("Select &All");

+        mitSelectAll.setData(new StandardTextFieldAction(text,

+                StandardTextFieldAction.SELECT_ALL));

+        mitSelectAll.addSelectionListener(this);

+    }

+

+    public void widgetSelected(SelectionEvent e) {

+        Widget widget = e.widget;

+        Object data = widget.getData();

+

+        // selected one of the standard text field menu commands

+        // Cut, Copy, Paste, Select All

+        if (data instanceof StandardTextFieldAction) {

+            ((StandardTextFieldAction) data).perform();

+        }

+

+        // Selected MenuItem "Copy As String Literal"

+        if (widget == mit_CopyLiteral) {

+            Clipboard clipboard = new Clipboard(e.display);

+            TextTransfer textTransfer = TextTransfer.getInstance();

+            clipboard.setContents(new Object[] { regex.getRegExAsLiteral() },

+                    new Transfer[] { textTransfer });

+            clipboard.dispose();

+        }

+

+        if (widget == mit_mFind || widget == mit_mMatch

+                || widget == mit_mReplace || widget == mit_mSplit) {

+            MenuItem menuItem = (MenuItem) widget;

+            if (menuItem.getSelection()) {

+                int mode = ((Integer) data).intValue();

+                setMatchMode(mode);

+                if (liveEval.isLiveEval()) {

+                    processRegEx();

+                    updateFoundStatus();

+                }

+            }

+        }

+

+        if (widget == mit_PasteLiteral) {

+            pasteLiteral(e.display);

+        }

+

+        // Selected MenuItem "Replace ..."

+        if (widget == mit_mReplace) {

+            MenuItem menuItem = (MenuItem) widget;

+            if (menuItem.getSelection())

+                activateReplaceMode();

+        }

+        

+        if (widget == btn_Find) {

+        	processRegEx();

+        	updateFoundStatus();

+        }

+

+    }

+

+    private void setMatchMode(int mode) {

+        regex.setMatchMode(mode);

+        btn_Find.setText(modeLabels[mode]);

+        MenuItem[] modeItems = men_MatchMode.getItems();

+        if (!modeItems[mode].getSelection()) {

+            for (int i = 0; i < modeItems.length; i++) {

+                modeItems[i].setSelection(false);

+            }

+            modeItems[mode].setSelection(true);

+        }

+     }

+

+    private void pasteLiteral(Display display) {

+        Clipboard clipboard = new Clipboard(display);

+        TextTransfer textTransfer = TextTransfer.getInstance();

+        String clipboardText = (String) clipboard.getContents(textTransfer);

+        clipboard.dispose();

+

+        if (clipboardText != null) {

+            StringBuffer out = new StringBuffer();

+            char[] chars = clipboardText.toCharArray();

+            boolean lastWasBackslash = false;

+            for (int i = 0; i < chars.length; i++) {

+                if (chars[i] == '\\') {

+                    if (lastWasBackslash) {

+                        out.append(chars[i]);

+                        lastWasBackslash = false;

+                    } else {

+                        lastWasBackslash = true;

+                    }

+                } else {

+                    out.append(chars[i]);

+                }

+

+            }

+

+            txt_RegExp.insert(out.toString());

+        }

+    }

+

+    private void activateReplaceMode() {

+        InputDialog inputDialog = new InputDialog(

+                getViewSite().getShell(),

+                "Replace Match by ...",

+                "Enter a value which should be used to replace every instance of a found match:",

+                regex.getReplace(), new IInputValidator() {

+

+                    public String isValid(String newText) {

+                        // TODO Auto-generated method stub

+                        return null;

+                    }

+                });

+        int retCode = inputDialog.open();

+

+        if (retCode == Window.OK) {

+            String replace = inputDialog.getValue();

+

+            regex.setMatchMode(RegExModel.MODE_REPLACE);

+            regex.setReplace(replace);

+

+            btn_Find.setText(modeLabels[RegExModel.MODE_REPLACE]);

+

+            if (liveEval.isLiveEval()) {

+                processRegEx();

+                updateFoundStatus();

+            }

+        }

+    }

+

+    public void widgetDefaultSelected(SelectionEvent e) {

+        // do nothing

+    }

+

+    private void processRegEx() {

+        updateModel();

+        regex.process();

+    }

+    

+    public void updateModel() {

+        regex.setRegExp(txt_RegExp.getText());

+        regex.setSearchText(txt_SearchText.getText());       

+    }

+    

+    public void updateView(Expression state) {

+        updateView(state.getName(), state.getRegex(), state.getSearchText(), state.getMatchMode(), state.getPatternFlag());

+        updateModel();

+    }

+    

+    public void updateView(String descr, String regEx, String search, int matchMode, int patternFlags) {

+        txt_RegExp.setText(regEx);

+        txt_SearchText.setText(search);

+        setMatchMode(matchMode);

+        setPatternFlags(patternFlags);

+        setRegExDecription(descr);

+    }

+

+

+

+    private void setRegExDecription(String descr) {

+        

+        regex.setDescription(descr);

+    }

+

+    private void setPatternFlags(int patternFlags) {

+        MenuItem[] flagItems = men_PatternFlags.getItems();

+        for (int i = 0; i < flagItems.length; i++) {

+            if (flagItems[i].getData() == null)

+                continue;

+            if ((patternFlags & ((Integer) flagItems[i].getData()).intValue()) != 0) {

+                flagItems[i].setSelection(true);

+            } else {

+                flagItems[i].setSelection(false);

+            }

+        }

+        

+    }

+

+    private void displayReplace(ReplaceResult replaceResult) {

+        StringBuffer out = new StringBuffer("Replaced "

+                + replaceResult.getMatches().getMatchCount()

+                + " match(es):\n\n");

+        out.append(replaceResult.getResultText());

+        txt_Result.setText(out.toString());

+    }

+

+    private void displaySplit(String[] splitResult) {

+        StringBuffer out = new StringBuffer("Split text into "

+                + splitResult.length + " parts:\n\n");

+        for (int i = 0; i < splitResult.length; i++) {

+            out.append("part ");

+            out.append(i);

+            out.append(" = ");

+            out.append(splitResult[i]);

+            out.append("\n\n");

+        }

+        out.append(txt_Result.getText());

+        txt_Result.setText(out.toString());

+    }

+

+    private void displayMatches(Matches matches) {

+        StringBuffer out = new StringBuffer("Found " + matches.getMatchCount()

+                + " match(es):\n\n");

+        txt_SearchText.setStyleRange(null);

+

+        StyleRange[] styleRanges = new StyleRange[matches.getMatchCount()];

+        int c = 0;

+

+        for (Iterator i = matches.iterator(); i.hasNext();) {

+            Match match = (Match) i.next();

+

+            styleRanges[c++] = new StyleRange(match.getStart(), match.getEnd()

+                    - match.getStart(), COLOR_RED, COLOR_WHITE);

+

+            out.append("start=");

+            out.append(match.getStart());

+            out.append(", end=");

+            out.append(match.getEnd());

+            out.append("\n");

+            for (Iterator groups = match.getGroups().iterator(); groups

+                    .hasNext();) {

+                Group group = (Group) groups.next();

+                out.append("Group(");

+                out.append(group.getIndex());

+                out.append(") = ");

+                out.append(group.getText());

+                out.append("\n");

+            }

+

+            out.append("\n");

+

+        }

+        txt_SearchText.setStyleRanges(styleRanges);

+        txt_Result.setText(out.toString());

+    }

+

+

+	public void foundMatches(Matches matches) {

+        displayMatches(matches);		

+	}

+

+

+	public void foundNoMatches() {

+        txt_SearchText.setStyleRange(null);

+        txt_Result.setText("No matches found!");

+	}

+

+

+	public void expressionError(String errMsg) {

+        txt_Result.setText("A Syntax Error occured: \\n" + errMsg);		

+	}

+

+	public void doneWithReplace(ReplaceResult result) {

+        displayReplace(result);

+	}

+

+	public void doneWithSplit(String[] result) {

+        displaySplit(result);		

+	}

+

+

+	public void evalActivated() {

+        btn_LiveEval.setSelection(true);

+        processRegEx();

+        updateFoundStatus();

+	}

+

+

+	public void evalDeactivated() {

+		 btn_LiveEval.setSelection(false);	

+	}

+

+

+	public void evalDone() {

+		updateFoundStatus();

+	}

+

+

+	public void doEval() {

+		processRegEx();	

+	}

+

+

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.regex.IRegExListener#updateRequested()

+     */

+    public void updateRequested() {

+        updateModel();

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.ui.regex.view.IExpressionLoaderListener#loadExpression(org.eclipse.ui.regex.view.Expression)

+     */

+    public void loadExpression(Expression expression) {

+        updateView(expression);

+    }

+

+    protected void setRegExFont(FontData fontData) {

+        txt_RegExp.setFont(new Font(Display.getCurrent(), fontData));

+    }

+

+    /* (non-Javadoc)

+     * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)

+     */

+    public void propertyChange(PropertyChangeEvent event) {

+       if (event.getProperty().startsWith("font.")) {

+           txt_RegExp.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.regex.name"), prefs.getInt("font.regex.height"), prefs.getInt("font.regex.style")))); 

+           txt_SearchText.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.searchtext.name"), prefs.getInt("font.searchtext.height"), prefs.getInt("font.searchtext.style")))); 

+           txt_Result.setFont(new Font(Display.getCurrent(), new FontData(prefs.getString("font.result.name"), prefs.getInt("font.result.height"), prefs.getInt("font.result.style")))); 

+       }

+        

+    }

+ 

+    

+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/SaveLastValueToPreferenceStoreFocusAdapter.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/SaveLastValueToPreferenceStoreFocusAdapter.java
new file mode 100644
index 0000000..ca0860c
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/SaveLastValueToPreferenceStoreFocusAdapter.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2012  Andreas Groll
+ *  
+ * All rights reserved. 
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Andreas Groll - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.ui.regex.view;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Saves the last text value from a widget when focus is lost to {@link IPreferenceStore}.
+ * PreferenceStore will be automatically saved by
+ * {@link org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)}.
+ * <p>
+ * The current version support only {@link StyledText}, but it can be easily extended, if
+ * needed.
+ * @author Andreas Groll
+ */
+public class SaveLastValueToPreferenceStoreFocusAdapter extends FocusAdapter {
+
+	private final IPreferenceStore preferenceStore;
+	private final String preferenceKey;
+
+	/**
+	 * Constructor.
+	 * @param preferenceStore PreferenceStore to store value.
+	 * @param preferenceKey Name of the key to store value.
+	 */
+	public SaveLastValueToPreferenceStoreFocusAdapter(final IPreferenceStore preferenceStore,
+		final String preferenceKey) {
+
+		this.preferenceStore = preferenceStore;
+		this.preferenceKey = preferenceKey;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void focusLost(final FocusEvent e) {
+
+		// Init
+		String value = null;
+
+		// Current version supports only StyledText and Text, but can be extended, if needed
+		if (e.widget instanceof StyledText) {
+			StyledText styledText = (StyledText)e.widget;
+			value = styledText.getText();
+		} else if (e.widget instanceof Text) {
+			Text text = (Text)e.widget;
+			value = text.getText();
+		} else {
+			// Unusupported widget type
+			return;
+		}
+
+		// Put to preference store
+		preferenceStore.setValue(preferenceKey, value == null ? "" : value);
+	}
+}
diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/AboutAction.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/AboutAction.java
new file mode 100644
index 0000000..59e96fb
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/AboutAction.java
@@ -0,0 +1,49 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view.actions;

+

+import java.util.Dictionary;

+

+import org.eclipse.jface.action.Action;

+import org.eclipse.jface.dialogs.MessageDialog;

+import org.eclipse.ui.regex.RegExPlugin;

+import org.eclipse.ui.regex.view.RegExView;

+

+

+public class AboutAction extends Action {

+

+	private RegExView view;

+	

+    public AboutAction(RegExView view) {

+		setText("About");

+		this.view = view;

+    }

+    

+    /* (non-Javadoc)

+     * @see org.eclipse.jface.action.Action#run()

+     */

+    public void run() {

+    	Dictionary d = RegExPlugin.getDefault().getBundle().getHeaders();

+    	String version = (String) d.get(org.osgi.framework.Constants.BUNDLE_VERSION);

+    	

+		String msg = "Regular Expression Tester " + version + "\n";

+		msg += "(C) 2006-2012 by Stephan Brosinski <sbrosinski@gmail.com>\n\n";

+		msg += "https://github.com/sbrosinski/RegexTester \n";

+		

+

+		MessageDialog.openInformation(view.getSite().getShell(), "About RegexTester", msg);     

+        

+        

+    }

+    

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearAction.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearAction.java
new file mode 100644
index 0000000..2254ebd
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearAction.java
@@ -0,0 +1,46 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.jface.action.Action;

+import org.eclipse.jface.resource.ImageDescriptor;

+import org.eclipse.ui.regex.RegExPlugin;

+import org.eclipse.ui.regex.view.RegExView;

+

+public class ClearAction extends Action {

+	public static final int	MODE_REGEX	= 0;

+	public static final int	MODE_SEARCH	= 1;

+	public static final int	MODE_RESULT	= 2;

+	public static final int	MODE_ALL	= 3;

+

+	private static ImageDescriptor image = RegExPlugin.getDefault().getImageDescriptor("clear_co.gif");

+	private int mode = MODE_ALL;

+	private RegExView view;

+	

+

+	public ClearAction(RegExView regExView) {

+		super("ClearAction", image);

+		view = regExView;

+		setToolTipText("Clear...");

+		setMenuCreator(new ClearActionMenuCreator(this));

+	}

+

+	public void setMode(int aMode) {

+		mode =aMode;

+	}

+	

+	public void run() {

+	    view.clear(mode);

+	    view.updateFoundStatus();

+	}

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearActionMenuCreator.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearActionMenuCreator.java
new file mode 100644
index 0000000..68d1fea
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/ClearActionMenuCreator.java
@@ -0,0 +1,89 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.jface.action.IMenuCreator;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.events.SelectionAdapter;

+import org.eclipse.swt.events.SelectionEvent;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.swt.widgets.Menu;

+import org.eclipse.swt.widgets.MenuItem;

+

+

+public class ClearActionMenuCreator implements IMenuCreator {

+

+	Menu menu;

+	ClearAction clearAction;

+	ClearSelection clearSelection = new ClearSelection();

+	

+	class ClearSelection extends SelectionAdapter {

+		public void widgetSelected(SelectionEvent e) {

+			MenuItem menuItem = (MenuItem) e.widget;

+			boolean selected = menuItem.getSelection();

+			int mode=((Integer)menuItem.getData()).intValue();

+			

+			if (selected) {

+				clearAction.setMode(mode);

+			}

+		}			

+	}	

+	

+	public ClearActionMenuCreator(ClearAction action) {

+		clearAction = action;

+	}

+

+	public void dispose() {

+		if (menu != null) {

+			menu.dispose();		

+		}

+	}

+

+

+	public Menu getMenu(Control parent) {

+		if (menu != null) {

+			return menu;

+		}

+		

+		menu = new Menu(parent);

+

+		MenuItem mitClearBoth= new MenuItem(menu,SWT.RADIO);

+		mitClearBoth.setData(new Integer(ClearAction.MODE_ALL));

+		mitClearBoth.setText("Everything");

+		mitClearBoth.addSelectionListener(clearSelection);

+		mitClearBoth.setSelection(true);

+		

+		MenuItem mitClearRegEx = new MenuItem(menu, SWT.RADIO);

+		mitClearRegEx.setText("Regular Expression");

+		mitClearRegEx.setData(new Integer(ClearAction.MODE_REGEX));

+		mitClearRegEx.addSelectionListener(clearSelection);

+	

+		MenuItem mitClearSearch= new MenuItem(menu,SWT.RADIO);

+		mitClearSearch.setData(new Integer(ClearAction.MODE_SEARCH));

+		mitClearSearch.setText("Search Text");

+		mitClearSearch.addSelectionListener(clearSelection);

+		

+		MenuItem mitClearResult= new MenuItem(menu,SWT.RADIO);

+		mitClearResult.setData(new Integer(ClearAction.MODE_RESULT));

+		mitClearResult.setText("Result");

+		mitClearResult.addSelectionListener(clearSelection);

+		

+		

+		return menu;

+	}

+

+

+	public Menu getMenu(Menu parent) {

+		return null;

+	}

+

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/NextMatchAction.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/NextMatchAction.java
new file mode 100644
index 0000000..878cc62
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/NextMatchAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.jface.action.Action;

+import org.eclipse.jface.resource.ImageDescriptor;

+import org.eclipse.ui.regex.RegExPlugin;

+import org.eclipse.ui.regex.view.RegExView;

+

+public class NextMatchAction extends Action {

+	private static ImageDescriptor image  = RegExPlugin.getDefault().getImageDescriptor("forward_nav.gif");

+	private RegExView view;

+	

+	public NextMatchAction(RegExView regExView) { 

+		super("NextMatchAction", image);

+		view = regExView;

+		setEnabled(false);

+		setToolTipText("Show Next Match");

+	}

+	

+	public void run() {

+	    view.selectNextMatch();

+	    view.updateFoundStatus();

+	}

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/PrevMatchAction.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/PrevMatchAction.java
new file mode 100644
index 0000000..ff49112
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/PrevMatchAction.java
@@ -0,0 +1,36 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.jface.action.Action;

+import org.eclipse.jface.resource.ImageDescriptor;

+import org.eclipse.ui.regex.RegExPlugin;

+import org.eclipse.ui.regex.view.RegExView;

+

+public class PrevMatchAction extends Action {

+	private static ImageDescriptor image  = RegExPlugin.getDefault().getImageDescriptor("backward_nav.gif");

+	private RegExView view;

+	

+	public PrevMatchAction(RegExView regExView) { 

+		super("PrevMatchAction", image);

+		view = regExView;

+		setEnabled(false);

+		setToolTipText("Show Previous Match");

+	}

+	

+	public void run() {

+	    view.selectPreviousMatch();

+	    view.updateFoundStatus();

+	}

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StandardTextFieldAction.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StandardTextFieldAction.java
new file mode 100644
index 0000000..3173827
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StandardTextFieldAction.java
@@ -0,0 +1,39 @@
+/*******************************************************************************

+ * Copyright (c) 2012 Stephan Brosinski

+ *  

+ * All rights reserved. 

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,

+ * and is available at http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *   Stephan Brosinski - initial API and implementation

+ ******************************************************************************/

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.swt.custom.StyledText;

+

+

+public class StandardTextFieldAction {

+	

+	private StyledText styledText;

+	private int type;

+	

+	public static final int COPY 	   = 1;

+	public static final int CUT 	   = 2;

+	public static final int PASTE	   = 3;

+	public static final int SELECT_ALL = 4;

+	

+	public StandardTextFieldAction(StyledText styledText,int type) {

+		this.styledText = styledText;

+		this.type = type;

+	}

+	

+	public void perform() {

+		if (type == COPY) 		styledText.copy();

+		if (type == CUT) 		styledText.cut();

+		if (type == PASTE)	 	styledText.paste();

+		if (type == SELECT_ALL) styledText.selectAll();

+	}

+	

+}

diff --git a/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StyledTextActionHandler.java b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StyledTextActionHandler.java
new file mode 100644
index 0000000..6b7638d
--- /dev/null
+++ b/bundles/org.eclipse.ui.regex/src/org/eclipse/ui/regex/view/actions/StyledTextActionHandler.java
@@ -0,0 +1,460 @@
+/*******************************************************************************

+ * Copyright (c) 2000, 2003 IBM Corporation and others.

+ * All rights reserved. This program and the accompanying materials 

+ * are made available under the terms of the Common Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/cpl-v10.html

+ * 

+ * Contributors:

+ *     IBM Corporation - initial API and implementation

+ *******************************************************************************/

+

+/*

+ * This class is based on IBM's TextActionHandler. It has been altered

+ * so it works with StyledText widgets instead

+ * 

+ */

+ 

+package org.eclipse.ui.regex.view.actions;

+

+import org.eclipse.jface.action.Action;

+import org.eclipse.jface.action.IAction;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.custom.StyledText;

+import org.eclipse.swt.events.KeyAdapter;

+import org.eclipse.swt.events.KeyEvent;

+import org.eclipse.swt.events.MouseAdapter;

+import org.eclipse.swt.events.MouseEvent;

+import org.eclipse.swt.widgets.Event;

+import org.eclipse.swt.widgets.Listener;

+import org.eclipse.ui.IActionBars;

+import org.eclipse.ui.actions.ActionFactory;

+

+

+/**

+ * Handles the redirection of the global Cut, Copy, Paste, and

+ * Select All actions to either the current inline text control

+ * or the part's supplied action handler.

+ * <p>

+ * This class may be instantiated; it is not intended to be subclassed.

+ * </p><p>

+ * Example usage:

+ * <pre>

+ * textActionHandler = new TextActionHandler(this.getViewSite().getActionBars());

+ * textActionHandler.addText((Text)textCellEditor1.getControl());

+ * textActionHandler.addText((Text)textCellEditor2.getControl());

+ * textActionHandler.setSelectAllAction(selectAllAction);

+ * </pre>

+ * </p>

+ */

+public class StyledTextActionHandler {

+	private DeleteActionHandler textDeleteAction = new DeleteActionHandler();

+	private CutActionHandler textCutAction = new CutActionHandler();

+	private CopyActionHandler textCopyAction = new CopyActionHandler();

+	private PasteActionHandler textPasteAction = new PasteActionHandler();

+	private SelectAllActionHandler textSelectAllAction = new SelectAllActionHandler();

+	

+	private IAction deleteAction;

+	private IAction cutAction;

+	private IAction copyAction;

+	private IAction pasteAction;

+	private IAction selectAllAction;

+	

+	private IPropertyChangeListener deleteActionListener = new PropertyChangeListener(textDeleteAction);

+	private IPropertyChangeListener cutActionListener = new PropertyChangeListener(textCutAction);

+	private IPropertyChangeListener copyActionListener = new PropertyChangeListener(textCopyAction);

+	private IPropertyChangeListener pasteActionListener = new PropertyChangeListener(textPasteAction);

+	private IPropertyChangeListener selectAllActionListener = new PropertyChangeListener(textSelectAllAction);

+	

+	private Listener textControlListener = new TextControlListener();

+	private StyledText activeTextControl;

+	

+	private MouseAdapter mouseAdapter = new MouseAdapter() {

+		public void mouseUp(MouseEvent e) {

+			updateActionsEnableState();

+		}

+	};

+	private KeyAdapter keyAdapter = new KeyAdapter() {

+		public void keyReleased(KeyEvent e) {

+			updateActionsEnableState();

+		}

+	};

+	

+	private class TextControlListener implements Listener {

+		public void handleEvent(Event event) {

+			switch (event.type) {

+				case SWT.Activate:

+					activeTextControl = (StyledText) event.widget;

+					updateActionsEnableState();

+					break;

+				case SWT.Deactivate:

+					// added so only one of the styled text fields can

+					// have a selection, which I believe should be the default

+					// behaviour

+					activeTextControl.setSelection(0,0);

+					activeTextControl = null;

+					updateActionsEnableState();

+					break;

+				default:

+					break;

+			}

+		}

+	}

+	

+	private class PropertyChangeListener implements IPropertyChangeListener {

+		private IAction actionHandler;

+		protected PropertyChangeListener(IAction actionHandler) {

+			super();

+			this.actionHandler = actionHandler;

+		}

+		public void propertyChange(PropertyChangeEvent event) {

+			if (activeTextControl != null)

+				return;

+			if (event.getProperty().equals(IAction.ENABLED)) {

+				Boolean bool = (Boolean) event.getNewValue();

+				actionHandler.setEnabled(bool.booleanValue());

+			}

+		}

+	};

+

+	private class DeleteActionHandler extends Action {

+		protected DeleteActionHandler() {

+			super("Delete"); //$NON-NLS-1$

+			setId("TextDeleteActionHandler");//$NON-NLS-1$

+			setEnabled(false);

+		}

+		public void runWithEvent(Event event) {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				//this method doesn't exits in StyledText ??

+				//activeTextControl.clearSelection();

+				activeTextControl.setSelection(0,0);

+				return;

+			}

+			if (deleteAction != null) {

+				deleteAction.runWithEvent(event);

+				return;

+			}

+		}

+		public void updateEnabledState() {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				//if condition also had: activeTextControl.getCaretPosition() < activeTextControl.getCharCount() removed

+				// because method doesn't exist in StyledText

+				setEnabled(activeTextControl.getSelectionCount() > 0);

+				return;

+			}

+			if (deleteAction != null) {

+				setEnabled(deleteAction.isEnabled());

+				return;

+			}

+			setEnabled(false);

+		}

+	}

+	

+	private class CutActionHandler extends Action {

+		protected CutActionHandler() {

+			super("Cut"); //$NON-NLS-1$

+			setId("TextCutActionHandler");//$NON-NLS-1$

+			setEnabled(false);

+		}

+		public void runWithEvent(Event event) {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				activeTextControl.cut();

+				return;

+			}

+			if (cutAction != null) {

+				cutAction.runWithEvent(event);

+				return;

+			}

+		}

+		public void updateEnabledState() {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				setEnabled(activeTextControl.getSelectionCount() > 0);

+				return;

+			}

+			if (cutAction != null) {

+				setEnabled(cutAction.isEnabled());

+				return;

+			}

+			setEnabled(false);

+		}

+	}

+	

+	private class CopyActionHandler extends Action {

+		protected CopyActionHandler() {

+			super("Copy"); //$NON-NLS-1$

+			setId("TextCopyActionHandler");//$NON-NLS-1$

+			setEnabled(false);

+		}

+		public void runWithEvent(Event event) {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				activeTextControl.copy();

+				return;

+			}

+			if (copyAction != null) {

+				copyAction.runWithEvent(event);

+				return;

+			}

+		}

+		public void updateEnabledState() {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				setEnabled(activeTextControl.getSelectionCount() > 0);

+				return;

+			}

+			if (copyAction != null) {

+				setEnabled(copyAction.isEnabled());

+				return;

+			}

+			setEnabled(false);

+		}

+	}

+	

+	private class PasteActionHandler extends Action {

+		protected PasteActionHandler() {

+			super("Paste"); //$NON-NLS-1$

+			setId("TextPasteActionHandler");//$NON-NLS-1$

+			setEnabled(false);

+		}

+		public void runWithEvent(Event event) {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				activeTextControl.paste();

+				return;

+			}

+			if (pasteAction != null) {

+				pasteAction.runWithEvent(event);

+				return;

+			}

+		}

+		public void updateEnabledState() {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				setEnabled(true);

+				return;

+			}

+			if (pasteAction != null) {

+				setEnabled(pasteAction.isEnabled());

+				return;

+			}

+			setEnabled(false);

+		}

+	}

+	

+	private class SelectAllActionHandler extends Action {

+		protected SelectAllActionHandler() {

+			super("TextAction.selectAll"); //$NON-NLS-1$

+			setId("TextSelectAllActionHandler");//$NON-NLS-1$

+			setEnabled(false);

+		}

+		public void runWithEvent(Event event) {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				activeTextControl.selectAll();

+				return;

+			}

+			if (selectAllAction != null) {

+				selectAllAction.runWithEvent(event);

+				return;

+			}

+		}

+		public void updateEnabledState() {

+			if (activeTextControl != null && !activeTextControl.isDisposed()) {

+				setEnabled(true);

+				return;

+			}

+			if (selectAllAction != null) {

+				setEnabled(selectAllAction.isEnabled());

+				return;

+			}

+			setEnabled(false);

+		}

+	}

+/**

+ * Creates a <code>Text</code> control action handler

+ * for the global Cut, Copy, Paste, Delete, and Select All 

+ * of the action bar.

+ *

+ * @param actionBar the action bar to register global

+ *    action handlers for Cut, Copy, Paste, Delete, 

+ * 	  and Select All

+ */

+public StyledTextActionHandler(IActionBars actionBar) {

+	super();

+	actionBar.setGlobalActionHandler(ActionFactory.CUT.getId(), textCutAction);

+	actionBar.setGlobalActionHandler(ActionFactory.COPY.getId(), textCopyAction);

+	actionBar.setGlobalActionHandler(ActionFactory.PASTE.getId(), textPasteAction);

+	actionBar.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), textSelectAllAction);

+	actionBar.setGlobalActionHandler(ActionFactory.DELETE.getId(), textDeleteAction);

+}

+/**

+ * Add a <code>Text</code> control to the handler

+ * so that the Cut, Copy, Paste, Delete, and Select All 

+ * actions are redirected to it when active.

+ *

+ * @param textControl the inline <code>Text</code> control

+ */

+public void addStyledText(StyledText textControl) {

+	if (textControl == null)

+		return;

+

+	activeTextControl = textControl;

+	textControl.addListener(SWT.Activate, textControlListener);

+	textControl.addListener(SWT.Deactivate, textControlListener);

+

+	// We really want a selection listener but it is not supported so we

+	// use a key listener and a mouse listener to know when selection changes

+	// may have occured

+	textControl.addKeyListener(keyAdapter);

+	textControl.addMouseListener(mouseAdapter);	

+	

+}

+/**

+ * Dispose of this action handler

+ */

+public void dispose() {

+	setCutAction(null);

+	setCopyAction(null);

+	setPasteAction(null);

+	setSelectAllAction(null);

+	setDeleteAction(null);

+}

+/**

+ * Removes a <code>Text</code> control from the handler

+ * so that the Cut, Copy, Paste, Delete, and Select All 

+ * actions are no longer redirected to it when active.

+ *

+ * @param textControl the inline <code>Text</code> control

+ */

+public void removeStyledText(StyledText textControl) {

+	if (textControl == null)

+		return;

+

+	textControl.removeListener(SWT.Activate, textControlListener);

+	textControl.removeListener(SWT.Deactivate, textControlListener);

+

+	textControl.removeMouseListener(mouseAdapter);

+	textControl.removeKeyListener(keyAdapter);

+	

+	activeTextControl = null;

+	updateActionsEnableState();

+}

+/**

+ * Set the default <code>IAction</code> handler for the Copy

+ * action. This <code>IAction</code> is run only if no active

+ * inline text control.

+ *

+ * @param action the <code>IAction</code> to run for the

+ *    Copy action, or <code>null</null> if not interested.

+ */

+public void setCopyAction(IAction action) {

+	if (copyAction == action)

+		return;

+

+	if (copyAction != null)

+		copyAction.removePropertyChangeListener(copyActionListener);

+		

+	copyAction = action;

+

+	if (copyAction != null)

+		copyAction.addPropertyChangeListener(copyActionListener);

+

+	textCopyAction.updateEnabledState();

+}

+/**

+ * Set the default <code>IAction</code> handler for the Cut

+ * action. This <code>IAction</code> is run only if no active

+ * inline text control.

+ *

+ * @param action the <code>IAction</code> to run for the

+ *    Cut action, or <code>null</null> if not interested.

+ */

+public void setCutAction(IAction action) {

+	if (cutAction == action)

+		return;

+

+	if (cutAction != null)

+		cutAction.removePropertyChangeListener(cutActionListener);

+		

+	cutAction = action;

+

+	if (cutAction != null)

+		cutAction.addPropertyChangeListener(cutActionListener);

+

+	textCutAction.updateEnabledState();

+}

+/**

+ * Set the default <code>IAction</code> handler for the Paste

+ * action. This <code>IAction</code> is run only if no active

+ * inline text control.

+ *

+ * @param action the <code>IAction</code> to run for the

+ *    Paste action, or <code>null</null> if not interested.

+ */

+public void setPasteAction(IAction action) {

+	if (pasteAction == action)

+		return;

+

+	if (pasteAction != null)

+		pasteAction.removePropertyChangeListener(pasteActionListener);

+		

+	pasteAction = action;

+

+	if (pasteAction != null)

+		pasteAction.addPropertyChangeListener(pasteActionListener);

+

+	textPasteAction.updateEnabledState();

+}

+/**

+ * Set the default <code>IAction</code> handler for the Select All

+ * action. This <code>IAction</code> is run only if no active

+ * inline text control.

+ *

+ * @param action the <code>IAction</code> to run for the

+ *    Select All action, or <code>null</null> if not interested.

+ */

+public void setSelectAllAction(IAction action) {

+	if (selectAllAction == action)

+		return;

+

+	if (selectAllAction != null)

+		selectAllAction.removePropertyChangeListener(selectAllActionListener);

+		

+	selectAllAction = action;

+

+	if (selectAllAction != null)

+		selectAllAction.addPropertyChangeListener(selectAllActionListener);

+

+	textSelectAllAction.updateEnabledState();

+}

+/**

+ * Set the default <code>IAction</code> handler for the Delete

+ * action. This <code>IAction</code> is run only if no active

+ * inline text control.

+ *

+ * @param action the <code>IAction</code> to run for the

+ *    Delete action, or <code>null</null> if not interested.

+ */

+public void setDeleteAction(IAction action) {

+	if (deleteAction == action)

+		return;

+

+	if (deleteAction != null)

+		deleteAction.removePropertyChangeListener(deleteActionListener);

+		

+	deleteAction = action;

+

+	if (deleteAction != null)

+		deleteAction.addPropertyChangeListener(deleteActionListener);

+

+	textDeleteAction.updateEnabledState();

+}

+/**

+ * Update the enable state of the Cut, Copy,

+ * Paste, Delete, and Select All action handlers

+ */

+private void updateActionsEnableState() {

+	textCutAction.updateEnabledState();

+	textCopyAction.updateEnabledState();

+	textPasteAction.updateEnabledState();

+	textSelectAllAction.updateEnabledState();

+	textDeleteAction.updateEnabledState();

+}

+}