3m9 compatible;
authorkhartlage <khartlage>
Sun, 30 May 2004 10:27:29 +0000 (10:27 +0000)
committerkhartlage <khartlage>
Sun, 30 May 2004 10:27:29 +0000 (10:27 +0000)
removed xerces dependency
first version for code folding (only methods;must enable preferences)

30 files changed:
net.sourceforge.phpeclipse/.project
net.sourceforge.phpeclipse/plugin.properties
net.sourceforge.phpeclipse/plugin.xml
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/jdom/DOMFactory.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/parser/UnitParser.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/compiler/util/Util.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/corext/template/TemplateSet.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/ActionMessages.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/AddBlockCommentAction.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/RemoveBlockCommentAction.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/JavaStringAutoIndentStrategy.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/BestMatchHover.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/link/LinkedPositionManager.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemMarkerManager.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/text/JavaTextTools.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormatter.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/html/HTMLFormattingStrategy.java

index 6aa6c77..f592e9e 100644 (file)
@@ -28,3 +28,4 @@
                <nature>org.eclipse.pde.PluginNature</nature>
        </natures>
 </projectDescription>
+
index 3673587..e03c089 100644 (file)
@@ -49,6 +49,9 @@ htmFileExtension=htm
 xmlFileExtension=xml
 tplFileExtension=tpl
 
+javaDocumentFactory=PHP Document Factory
+javaDocumentSetupParticipant=PHP Document Setup Participant
+
 sourceHover= Source
 sourceHoverDescription= Shows the source of the selected element.
 javadocHover= PHPdoc
@@ -369,6 +372,10 @@ Program.externalTools = PHP Program
 
 OccurrenceAnnotation.label= PHP Marker Occurrences
 
-
 phpEditorFontDefiniton.label= Java Editor Text Font
 phpEditorFontDefintion.description= The Java editor text font is used by Java editors.
+
+#--- folding
+foldingStructureProvidersExtensionPoint= Folding Structure Providers
+defaultFoldingStructureProviderName= Default PHP Folding
+Folding.label= F&olding
\ No newline at end of file
index 1eb9e64..a872078 100644 (file)
@@ -31,7 +31,6 @@
       <import plugin="org.eclipse.help"/>
       <import plugin="org.eclipse.swt"/>
       <import plugin="org.eclipse.search"/>
-      <import plugin="org.apache.xerces"/>
       <import plugin="org.eclipse.update.ui"/>
       <import plugin="net.sourceforge.phpeclipse.quantum.sql"/> 
    </requires>
@@ -89,8 +88,8 @@
     <persistent value="true"/>
 </extension>
 
-   <extension-point name="%phpEditorTextHoversName" id="phpEditorTextHovers" schema="schema/phpEditorTextHovers.exsd"/> 
-
+   <extension-point id="phpEditorTextHovers" name="%phpEditorTextHoversName" schema="schema/phpEditorTextHovers.exsd"/> 
+   <extension-point id="foldingStructureProviders" name="%foldingStructureProvidersExtensionPoint" schema="schema/foldingStructureProviders.exsd"/>
    <extension
          point="org.eclipse.team.core.fileTypes">
       <fileTypes
          </action>
       </viewerContribution>
    </extension>
+   <extension
+         point="org.eclipse.ui.popupMenus">
+      <viewerContribution
+            targetID="#CompilationUnitRulerContext"
+            id="net.sourceforge.phpdt.ui.CompilationUnitEditorPopupActions">
+         <action
+               label="%AddTask.label"
+               helpContextId="org.eclipse.ui.AddTask_action_context"
+               tooltip="%AddTask.tooltip"
+               class="org.eclipse.ui.texteditor.TaskRulerAction"
+               menubarPath="add"
+               id="org.eclipse.ui.texteditor.TaskRulerAction">
+         </action>
+         <action
+               label="%AddBookmark.label"
+               helpContextId="org.eclipse.ui.bookmark_action_context"
+               tooltip="%AddBookmark.tooltip"
+               class="org.eclipse.ui.texteditor.BookmarkRulerAction"
+               menubarPath="add"
+               id="org.eclipse.ui.texteditor.BookmarkRulerAction">
+         </action>
+         <menu
+                       id="projection"
+                       label="%Folding.label"
+                       path="rest">
+                </menu>
+         <action
+               label="%Dummy.label"
+               tooltip="%Dummy.label"
+               class="net.sourceforge.phpdt.internal.ui.actions.FoldingExpandAllRulerAction"
+               menubarPath="projection/additions"
+               definitionId="org.eclipse.ui.edit.text.folding.expand_all"
+               id="net.sourceforge.phpdt.ui.folding.expandAll">
+         </action>
+         <action
+               label="%Dummy.label"
+               tooltip="%Dummy.label"
+               class="net.sourceforge.phpdt.internal.ui.actions.FoldingToggleRulerAction"
+               menubarPath="projection/additions"
+               definitionId="org.eclipse.ui.edit.text.folding.toggle"
+               id="net.sourceforge.phpdt.ui.folding.toggle">
+         </action>
+      </viewerContribution>
+   </extension>
  <!-- =========================================================================== -->
 <!-- JDT/UI command definitions                                                   -->
 <!-- =========================================================================== -->
       </keyBinding>
    </extension>
    <extension
+         id="net.sourceforge.phpeclipse.JavaDocumentSetupParticipant"
+         name="%javaDocumentSetupParticipant"
+         point="org.eclipse.core.filebuffers.documentSetup"> 
+      <participant
+            extensions="php,php3,php4,inc"
+            class="net.sourceforge.phpeclipse.phpeditor.JavaDocumentSetupParticipant">
+      </participant>
+      <participant
+            extensions="html,xml"
+            class="net.sourceforge.phpeclipse.phpeditor.HTMLDocumentSetupParticipant">
+      </participant>
+      <participant
+            extensions="tpl"
+            class="net.sourceforge.phpeclipse.phpeditor.SmartyDocumentSetupParticipant">
+      </participant>
+   </extension>
+   <extension
+         id="net.sourceforge.phpeclipse.JavaDocumentFactory"
+         name="%javaDocumentFactory"
+         point="org.eclipse.core.filebuffers.documentCreation">
+      <factory
+            extensions="php"
+            class="net.sourceforge.phpeclipse.phpeditor.JavaDocumentFactory">
+      </factory>
+   </extension>
+   
+   <extension
          point="org.eclipse.ui.preferencePages">
       <page
             name="PHP"
                        expanderClass="net.sourceforge.phpdt.externaltools.variable.WorkingSetExpander">
                </variable>
        </extension>
+               <extension
+               point= "net.sourceforge.phpeclipse.foldingStructureProviders">
+               <provider
+                       id="net.sourceforge.phpdt.ui.text.defaultFoldingProvider"
+                       name= "%defaultFoldingStructureProviderName"
+                       class="net.sourceforge.phpdt.internal.ui.text.folding.DefaultJavaFoldingStructureProvider"
+                       preferencesClass="net.sourceforge.phpdt.internal.ui.text.folding.DefaultJavaFoldingPreferenceBlock">
+               </provider>
+       </extension>
 </plugin>
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/core/dom/CompilationUnit.java
new file mode 100644 (file)
index 0000000..9053d2b
--- /dev/null
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.core.dom;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Java compilation unit AST node type. This is the type of the root of an AST.
+ * <p>
+ * The source range for this type of node is ordinarily the entire source file,
+ * including leading and trailing whitespace and comments.
+ * </p>
+ * For JLS2:
+ * <pre>
+ * CompilationUnit:
+ *    [ PackageDeclaration ]
+ *        { ImportDeclaration }
+ *        { TypeDeclaration | <b>;</b> }
+ * </pre>
+ * For JLS3, the kinds of type declarations
+ * grew to include enum and annotation type declarations:
+ * <pre>
+ * CompilationUnit:
+ *    [ PackageDeclaration ]
+ *        { ImportDeclaration }
+ *        { TypeDeclaration | EnumDeclaration | AnnotationTypeDeclaration | <b>;</b> }
+ * </pre>
+ * 
+ * @since 2.0
+ */
+public class CompilationUnit  {
+
+//     /**
+//      * The "package" structural property of this node type.
+//      * 
+//      * @since 3.0
+//      */
+//     public static final ChildPropertyDescriptor PACKAGE_PROPERTY = 
+//             new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+//     
+//     /**
+//      * The "imports" structural property of this node type.
+//      * 
+//      * @since 3.0
+//      */
+//     public static final ChildListPropertyDescriptor IMPORTS_PROPERTY =
+//             new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
+//     
+//     /**
+//      * The "types" structural property of this node type.
+//      * 
+//      * @since 3.0
+//      */
+//     public static final ChildListPropertyDescriptor TYPES_PROPERTY =
+//             new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+//     
+//     /**
+//      * A list of property descriptors (element type: 
+//      * {@link StructuralPropertyDescriptor}),
+//      * or null if uninitialized.
+//      * @since 3.0
+//      */
+//     private static final List PROPERTY_DESCRIPTORS;
+//     
+//     static {
+//             createPropertyList(CompilationUnit.class);
+//             addProperty(PACKAGE_PROPERTY);
+//             addProperty(IMPORTS_PROPERTY);
+//             addProperty(TYPES_PROPERTY);
+//             PROPERTY_DESCRIPTORS = reapPropertyList();
+//     }
+//
+//     /**
+//      * Returns a list of structural property descriptors for this node type.
+//      * Clients must not modify the result.
+//      * 
+//      * @param apiLevel the API level; one of the
+//      * <code>AST.JLS&ast;</code> constants
+//
+//      * @return a list of property descriptors (element type: 
+//      * {@link StructuralPropertyDescriptor})
+//      * @since 3.0
+//      */
+//     public static List propertyDescriptors(int apiLevel) {
+//             return PROPERTY_DESCRIPTORS;
+//     }
+//                     
+//     /**
+//      * The comment table, or <code>null</code> if none; initially
+//      * <code>null</code>. This array is the storage underlying
+//      * the <code>optionalCommentList</code> ArrayList.
+//      * @since 3.0
+//      */
+//     Comment[] optionalCommentTable = null;
+//     
+//     /**
+//      * The comment list (element type: <code>Comment</code>, 
+//      * or <code>null</code> if none; initially <code>null</code>.
+//      * @since 3.0
+//      */
+//     private List optionalCommentList = null;
+//     
+//     /**
+//      * The package declaration, or <code>null</code> if none; initially
+//      * <code>null</code>.
+//      */
+//     private PackageDeclaration optionalPackageDeclaration = null;
+//     
+//     /**
+//      * The list of import declarations in textual order order; 
+//      * initially none (elementType: <code>ImportDeclaration</code>).
+//      */
+//     private ASTNode.NodeList imports =
+//             new ASTNode.NodeList(IMPORTS_PROPERTY);
+//     
+//     /**
+//      * The list of type declarations in textual order order; 
+//      * initially none (elementType: <code>AbstractTypeDeclaration</code>)
+//      */
+//     private ASTNode.NodeList types =
+//             new ASTNode.NodeList(TYPES_PROPERTY);
+//     
+//     /**
+//      * Line end table. If <code>lineEndTable[i] == p</code> then the
+//      * line number <code>i+1</code> ends at character position 
+//      * <code>p</code>. Except for the last line, the positions are that
+//      * of the last character of the line delimiter. 
+//      * For example, the source string <code>A\nB\nC</code> has
+//      * line end table {1, 3} (if \n is one character).
+//      */
+//     private int[] lineEndTable = new int[0];
+//
+//     /**
+//      * Canonical empty list of messages.
+//      */
+//     private static final Message[] EMPTY_MESSAGES = new Message[0];
+//
+//     /**
+//      * Canonical empty list of problems.
+//      */
+//     private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
+//
+//     /**
+//      * Messages reported by the compiler during parsing or name resolution.
+//      */
+//     private Message[] messages;
+//     
+//     /**
+//      * Problems reported by the compiler during parsing or name resolution.
+//      */
+//     private IProblem[] problems = EMPTY_PROBLEMS;
+//     
+//     /**
+//      * The comment mapper, or <code>null</code> in none; 
+//      * initially <code>null</code>.
+//      * @since 3.0
+//      */
+//     private DefaultCommentMapper commentMapper = null;
+//     
+//     /**
+//      * Sets the line end table for this compilation unit.
+//      * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code> 
+//      * ends at character position <code>p</code>. Except for the last line, the 
+//      * positions are that of (the last character of) the line delimiter.
+//      * For example, the source string <code>A\nB\nC</code> has
+//      * line end table {1, 3, 4}.
+//      * 
+//      * @param lineEndtable the line end table
+//      */
+//     void setLineEndTable(int[] lineEndTable) {
+//             if (lineEndTable == null) {
+//                     throw new NullPointerException();
+//             }
+//             // alternate root is *not* considered a structural property
+//             // but we protect them nevertheless
+//             checkModifiable();
+//             this.lineEndTable = lineEndTable;
+//     }
+//
+//     /**
+//      * Creates a new AST node for a compilation owned by the given AST.
+//      * The compilation unit initially has no package declaration, no
+//      * import declarations, and no type declarations.
+//      * <p>
+//      * N.B. This constructor is package-private; all subclasses must be 
+//      * declared in the same package; clients are unable to declare 
+//      * additional subclasses.
+//      * </p>
+//      * 
+//      * @param ast the AST that is to own this node
+//      */
+//     CompilationUnit(AST ast) {
+//             super(ast);
+//     }
+//
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      * @since 3.0
+//      */
+//     final List internalStructuralPropertiesForType(int apiLevel) {
+//             return propertyDescriptors(apiLevel);
+//     }
+//     
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+//             if (property == PACKAGE_PROPERTY) {
+//                     if (get) {
+//                             return getPackage();
+//                     } else {
+//                             setPackage((PackageDeclaration) child);
+//                             return null;
+//                     }
+//             }
+//             // allow default implementation to flag the error
+//             return super.internalGetSetChildProperty(property, get, child);
+//     }
+//     
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+//             if (property == IMPORTS_PROPERTY) {
+//                     return imports();
+//             }
+//             if (property == TYPES_PROPERTY) {
+//                     return types();
+//             }
+//             // allow default implementation to flag the error
+//             return super.internalGetChildListProperty(property);
+//     }
+//     
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     final int getNodeType0() {
+//             return COMPILATION_UNIT;
+//     }
+//
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     ASTNode clone0(AST target) {
+//             CompilationUnit result = new CompilationUnit(target);
+//             // n.b do not copy line number table or messages
+//             result.setSourceRange(this.getStartPosition(), this.getLength());
+//             result.setPackage(
+//                     (PackageDeclaration) ASTNode.copySubtree(target, getPackage()));
+//             result.imports().addAll(ASTNode.copySubtrees(target, imports()));
+//             result.types().addAll(ASTNode.copySubtrees(target, types()));
+//             return result;
+//     }
+//
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+//             // dispatch to correct overloaded match method
+//             return matcher.match(this, other);
+//     }
+//
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     void accept0(ASTVisitor visitor) {
+//             boolean visitChildren = visitor.visit(this);
+//             if (visitChildren) {
+//                     // visit children in normal left to right reading order
+//                     acceptChild(visitor, getPackage());
+//                     acceptChildren(visitor, this.imports);
+//                     acceptChildren(visitor, this.types);
+//             }
+//             visitor.endVisit(this);
+//     }
+//     
+//     /**
+//      * Returns the node for the package declaration of this compilation 
+//      * unit, or <code>null</code> if this compilation unit is in the 
+//      * default package.
+//      * 
+//      * @return the package declaration node, or <code>null</code> if none
+//      */ 
+//     public PackageDeclaration getPackage() {
+//             return this.optionalPackageDeclaration;
+//     }
+//     
+//     /**
+//      * Sets or clears the package declaration of this compilation unit 
+//      * node to the given package declaration node.
+//      * 
+//      * @param pkgDecl the new package declaration node, or 
+//      *   <code>null</code> if this compilation unit does not have a package
+//      *   declaration (that is in the default package)
+//      * @exception IllegalArgumentException if:
+//      * <ul>
+//      * <li>the node belongs to a different AST</li>
+//      * <li>the node already has a parent</li>
+//      * </ul>
+//      */ 
+//     public void setPackage(PackageDeclaration pkgDecl) {
+//             ASTNode oldChild = this.optionalPackageDeclaration;
+//             preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+//             this.optionalPackageDeclaration = pkgDecl;
+//             postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+//     }
+//
+//     /**
+//      * Returns the live list of nodes for the import declarations of this 
+//      * compilation unit, in order of appearance.
+//      * 
+//      * @return the live list of import declaration nodes
+//      *    (elementType: <code>ImportDeclaration</code>)
+//      */ 
+//     public List imports() {
+//             return this.imports;
+//     }
+//     
+//     /**
+//      * Returns the live list of nodes for the top-level type declarations of this 
+//      * compilation unit, in order of appearance.
+//     * <p>
+//     * Note that in JLS3, the types may include both enum declarations
+//     * and annotation type declarations introduced in J2SE 1.5.
+//     * For JLS2, the elements are always <code>TypeDeclaration</code>.
+//     * </p>
+//      * 
+//      * @return the live list of top-level type declaration
+//      *    nodes (elementType: <code>AbstractTypeDeclaration</code>)
+//      */ 
+//     public List types() {
+//             return this.types;
+//     }
+//
+//     /**
+//      * Finds the corresponding AST node in the given compilation unit from 
+//      * which the given binding originated. Returns <code>null</code> if the
+//      * binding does not correspond to any node in this compilation unit.
+//      * This method always returns <code>null</code> if bindings were not requested
+//      * when this AST was built.
+//      * <p>
+//      * The following table indicates the expected node type for the various
+//      * different kinds of bindings:
+//      * <ul>
+//      * <li></li>
+//      * <li>package - a <code>PackageDeclaration</code></li>
+//      * <li>class or interface - a <code>TypeDeclaration</code> or a
+//      *    <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
+//      * <li>primitive type - none</li>
+//      * <li>array type - none</li>
+//      * <li>field - a <code>VariableDeclarationFragment</code> in a 
+//      *    <code>FieldDeclaration</code> </li>
+//      * <li>local variable - a <code>SingleVariableDeclaration</code>, or
+//      *    a <code>VariableDeclarationFragment</code> in a 
+//      *    <code>VariableDeclarationStatement</code> or 
+//      *    <code>VariableDeclarationExpression</code></li>
+//      * <li>method - a <code>MethodDeclaration</code> </li>
+//      * <li>constructor - a <code>MethodDeclaration</code> </li>
+//     * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
+//     * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
+//     * <li>enum type - an <code>EnumDeclaration</code></li>
+//     * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+//      * </ul>
+//      * </p>
+//      * <p>
+//      * Each call to {@link ASTParser#createAST(IProgressMonitor)} with a request for bindings
+//      * gives rise to separate universe of binding objects. This method always returns
+//      * <code>null</code> when the binding object comes from a different AST.
+//      * Use <code>findDeclaringNode(binding.getKey())</code> when the binding comes
+//      * from a different AST.
+//      * </p>
+//      * 
+//      * @param binding the binding
+//      * @return the corresponding node where the given binding is declared,
+//      * or <code>null</code> if the binding does not correspond to a node in this
+//      * compilation unit or if bindings were not requested when this AST was built
+//      * @see #findDeclaringNode(String)
+//      */
+//     public ASTNode findDeclaringNode(IBinding binding) {
+//             return this.ast.getBindingResolver().findDeclaringNode(binding);
+//     }
+//
+//     /**
+//      * Finds the corresponding AST node in the given compilation unit from 
+//      * which the binding with the given key originated. Returns
+//      * <code>null</code> if the corresponding node cannot be determined.
+//      * This method always returns <code>null</code> if bindings were not requested
+//      * when this AST was built.
+//      * <p>
+//      * The following table indicates the expected node type for the various
+//      * different kinds of binding keys:
+//      * <ul>
+//      * <li></li>
+//      * <li>package - a <code>PackageDeclaration</code></li>
+//      * <li>class or interface - a <code>TypeDeclaration</code> or a
+//      *    <code>AnonymousClassDeclaration</code> (for anonymous classes)</li>
+//      * <li>primitive type - none</li>
+//      * <li>array type - none</li>
+//      * <li>field - a <code>VariableDeclarationFragment</code> in a 
+//      *    <code>FieldDeclaration</code> </li>
+//      * <li>local variable - a <code>SingleVariableDeclaration</code>, or
+//      *    a <code>VariableDeclarationFragment</code> in a 
+//      *    <code>VariableDeclarationStatement</code> or 
+//      *    <code>VariableDeclarationExpression</code></li>
+//      * <li>method - a <code>MethodDeclaration</code> </li>
+//      * <li>constructor - a <code>MethodDeclaration</code> </li>
+//     * <li>annotation type - an <code>AnnotationTypeDeclaration</code></li>
+//     * <li>annotation type member - an <code>AnnotationTypeMemberDeclaration</code></li>
+//     * <li>enum type - an <code>EnumDeclaration</code></li>
+//     * <li>enum constant - an <code>EnumConstantDeclaration</code></li>
+//      * </ul>
+//      * </p>
+//      * <p>
+//      * Note that as explained in {@link IBinding#getKey() IBinding.getkey}
+//      * there may be no keys for finding the declaring node for local variables,
+//      * local or anonymous classes, etc.
+//      * </p>
+//      * 
+//      * @param key the binding key, or <code>null</code>
+//      * @return the corresponding node where a binding with the given
+//      * key is declared, or <code>null</code> if the key is <code>null</code>
+//      * or if the key does not correspond to a node in this compilation unit
+//      * or if bindings were not requested when this AST was built
+//      * @see IBinding#getKey()
+//      * @since 2.1
+//      */
+//     public ASTNode findDeclaringNode(String key) {
+//             return this.ast.getBindingResolver().findDeclaringNode(key);
+//     }
+//     
+//     /**
+//      * Returns the internal comment mapper.
+//      * 
+//      * @return the comment mapper, or <code>null</code> if none.
+//      * @since 3.0
+//      */
+//     DefaultCommentMapper getCommentMapper() {
+//             return this.commentMapper;
+//     }
+//
+//     /**
+//      * Initializes the internal comment mapper with the given
+//      * scanner.
+//      * 
+//      * @param scanner the scanner
+//      * @since 3.0
+//      */
+//     void initCommentMapper(Scanner scanner) {
+//             this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
+//             this.commentMapper.initialize(this, scanner);
+//     }
+//
+//     /**
+//      * Returns the extended start position of the given node. Unlike
+//      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()()},
+//      * the extended source range may include comments and whitespace
+//      * immediately before or after the normal source range for the node.
+//      * 
+//      * @param node the node
+//      * @return the 0-based character index, or <code>-1</code>
+//      *    if no source position information is recorded for this node
+//      * @see #getExtendedLength(ASTNode)
+//      * @since 3.0
+//      */
+//     public int getExtendedStartPosition(ASTNode node) {
+//             if (this.commentMapper == null) {
+//                     return -1;
+//             } else {
+//                     return this.commentMapper.getExtendedStartPosition(node);
+//             }
+//     }
+//
+//     /**
+//      * Returns the extended source length of the given node. Unlike
+//      * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()()},
+//      * the extended source range may include comments and whitespace
+//      * immediately before or after the normal source range for the node.
+//      * 
+//      * @param node the node
+//      * @return a (possibly 0) length, or <code>0</code>
+//      *    if no source position information is recorded for this node
+//      * @see #getExtendedStartPosition(ASTNode)
+//      * @since 3.0
+//      */
+//     public int getExtendedLength(ASTNode node) {
+//             if (this.commentMapper == null) {
+//                     return 0;
+//             } else {
+//                     return this.commentMapper.getExtendedLength(node);
+//             }
+//     }
+//             
+//     /**
+//      * Returns the line number corresponding to the given source character
+//      * position in the original source string. The initial line of the 
+//      * compilation unit is numbered 1, and each line extends through the
+//      * last character of the end-of-line delimiter. The very last line extends
+//      * through the end of the source string and has no line delimiter.
+//      * For example, the source string <code>class A\n{\n}</code> has 3 lines
+//      * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
+//      * Returns 1 for a character position that does not correspond to any
+//      * source line, or if no line number information is available for this
+//      * compilation unit.
+//      * 
+//      * @param position a 0-based character position, possibly
+//      *   negative or out of range
+//      * @return the 1-based line number, or <code>1</code> if the character
+//      *    position does not correspond to a source line in the original
+//      *    source file or if line number information is not known for this
+//      *    compilation unit
+//      * @see ASTParser
+//      */
+//     public int lineNumber(int position) {
+//             int length = lineEndTable.length;
+//             if (length == 0) {
+//                     // no line number info
+//                     return 1;
+//             }
+//             int low = 0;
+//             if (position <= lineEndTable[low]) {
+//                     // position illegal or before the first line delimiter
+//                     return 1;
+//             }
+//             // assert position > lineEndTable[low+1]  && low == 0
+//             int hi = length - 1;
+//             if (position > lineEndTable[hi]) {
+//                     // position beyond the last line separator
+//                     if (position >= getStartPosition() + getLength()) {
+//                             // this is beyond the end of the source length
+//                             return 1;
+//                     } else {
+//                             return length + 1;
+//                     }
+//             }
+//             // assert lineEndTable[low]  < position <= lineEndTable[hi]
+//             // && low == 0 && hi == length - 1 && low < hi
+//             
+//             // binary search line end table
+//             while (true) {
+//                     // invariant lineEndTable[low] < position <= lineEndTable[hi]
+//                     // && 0 <= low < hi <= length - 1
+//                     // reducing measure hi - low
+//                     if (low + 1 == hi) {
+//                             // assert lineEndTable[low] < position <= lineEndTable[low+1]
+//                             // position is on line low+1 (line number is low+2)
+//                             return low + 2;
+//                     }
+//                     // assert hi - low >= 2, so average is truly in between
+//                     int mid = (low + hi) / 2;
+//                     // assert 0 <= low < mid < hi <= length - 1
+//                     if (position <= lineEndTable[mid]) {
+//                             // assert lineEndTable[low] < position <= lineEndTable[mid]
+//                             // && 0 <= low < mid < hi <= length - 1
+//                             hi = mid;
+//                     } else {
+//                             // position > lineEndTable[mid]
+//                             // assert lineEndTable[mid] < position <= lineEndTable[hi]
+//                             // && 0 <= low < mid < hi <= length - 1
+//                             low = mid;
+//                     }
+//                     // in both cases, invariant reachieved with reduced measure
+//             }
+//     }
+//
+//     /**
+//      * Returns the list of messages reported by the compiler during the parsing 
+//      * or the type checking of this compilation unit. This list might be a subset of 
+//      * errors detected and reported by a Java compiler.
+//      * <p>
+//      * This list of messages is suitable for simple clients that do little
+//      * more than log the messages or display them to the user. Clients that
+//      * need further details should call <code>getProblems</code> to get
+//      * compiler problem objects.
+//      * </p>
+//      *
+//      * @return the list of messages, possibly empty
+//      * @see #getProblems()
+//      * @see ASTParser
+//      */
+//     public Message[] getMessages() {
+//             if (this.messages == null) {
+//                     int problemLength = this.problems.length;
+//                     if (problemLength == 0) {
+//                             this.messages = EMPTY_MESSAGES;
+//                     } else {
+//                             this.messages = new Message[problemLength];
+//                             for (int i = 0; i < problemLength; i++) {
+//                                     IProblem problem = this.problems[i];
+//                                     int start = problem.getSourceStart();
+//                                     int end = problem.getSourceEnd();
+//                                     messages[i] = new Message(problem.getMessage(), start, end - start + 1);
+//                             }
+//                     }
+//             }
+//             return this.messages;
+//     }
+//
+//     /**
+//      * Returns the list of detailed problem reports noted by the compiler
+//      * during the parsing or the type checking of this compilation unit. This
+//      * list might be a subset of errors detected and reported by a Java
+//      * compiler.
+//      * <p>
+//      * Simple clients that do little more than log the messages or display
+//      * them to the user should probably call <code>getMessages</code> instead.
+//      * </p>
+//      * 
+//      * @return the list of detailed problem objects, possibly empty
+//      * @see #getMessages()
+//      * @see ASTParser
+//      * @since 2.1
+//      */
+//     public IProblem[] getProblems() {
+//             return this.problems;
+//     }
+//
+//     /**
+//      * Sets the array of problems reported by the compiler during the parsing or
+//      * name resolution of this compilation unit.
+//      * 
+//      * @param problems the list of problems
+//      */
+//     void setProblems(IProblem[] problems) {
+//             if (problems == null) {
+//                     throw new IllegalArgumentException();
+//             }
+//             this.problems = problems;
+//     }
+//             
+//     /**
+//      * Returns a list of the comments encountered while parsing
+//      * this compilation unit.
+//      * <p>
+//      * Since the Java language allows comments to appear most anywhere
+//      * in the source text, it is problematic to locate comments in relation
+//      * to the structure of an AST. The one exception is doc comments 
+//      * which, by convention, immediately precede type, field, and
+//      * method declarations; these comments are located in the AST
+//      * by {@link  BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
+//      * Other comments do not show up in the AST. The table of comments
+//      * is provided for clients that need to find the source ranges of
+//      * all comments in the original source string. It includes entries
+//      * for comments of all kinds (line, block, and doc), arranged in order
+//      * of increasing source position. 
+//      * </p>
+//      * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
+//      * of a doc comment associated with a body declaration is the body
+//      * declaration node; for these comment nodes
+//      * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
+//      * (assuming an unmodified AST) reflecting the fact that these nodes
+//      * are property located in the AST for the compilation unit.
+//      * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
+//      * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
+//      * will return the comment node itself, indicating that these comment nodes
+//      * are not directly connected to the AST for the compilation unit. The 
+//      * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
+//      * method provides a way to navigate from a comment to its compilation
+//      * unit.
+//      * </p>
+//      * <p>
+//      * A note on visitors: The only comment nodes that will be visited when
+//      * visiting a compilation unit are the doc comments parented by body
+//      * declarations. To visit all comments in normal reading order, iterate
+//      * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
+//      * on each element.
+//      * </p>
+//      * <p>
+//      * Clients cannot modify the resulting list.
+//      * </p>
+//      * 
+//      * @return an unmodifiable list of comments in increasing order of source
+//      * start position, or <code>null</code> if comment information
+//      * for this compilation unit is not available
+//      * @see ASTParser
+//      * @since 3.0
+//      */
+//     public List getCommentList() {
+//             return this.optionalCommentList;
+//     }
+//     
+//     /**
+//      * Sets the list of the comments encountered while parsing
+//      * this compilation unit.
+//      * 
+//      * @param commentTable a list of comments in increasing order
+//      * of source start position, or <code>null</code> if comment
+//      * information for this compilation unit is not available
+//      * @exception IllegalArgumentException if the comment table is
+//      * not in increasing order of source position
+//      * @see #getCommentList()
+//      * @see ASTParser
+//      * @since 3.0
+//      */
+//     void setCommentTable(Comment[] commentTable) {
+//             // double check table to ensure that all comments have
+//             // source positions and are in strictly increasing order
+//             if (commentTable == null) {
+//                     this.optionalCommentList = null;
+//                     this.optionalCommentTable = null;
+//             } else {
+//                     int nextAvailablePosition = 0;
+//                     for (int i = 0; i < commentTable.length; i++) {
+//                             Comment comment = commentTable[i];
+//                             if (comment == null) {
+//                                     throw new IllegalArgumentException();
+//                             }
+//                             int start = comment.getStartPosition();
+//                             int length = comment.getLength();
+//                             if (start < 0 || length < 0 || start < nextAvailablePosition) {
+//                                     throw new IllegalArgumentException();
+//                             }
+//                             nextAvailablePosition = comment.getStartPosition() + comment.getLength();
+//                     }
+//                     this.optionalCommentTable = commentTable;
+//                     List commentList = Arrays.asList(commentTable);
+//                     // protect the list from further modification
+//                     this.optionalCommentList = Collections.unmodifiableList(commentList);
+//             }
+//     }
+//     
+//     
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     void appendDebugString(StringBuffer buffer) {
+//             buffer.append("CompilationUnit"); //$NON-NLS-1$
+//             // include the type names
+//             buffer.append("["); //$NON-NLS-1$
+//             for (Iterator it = types().iterator(); it.hasNext(); ) {
+//                     AbstractTypeDeclaration d = (AbstractTypeDeclaration) it.next();
+//                     buffer.append(d.getName().getIdentifier());
+//                     if (it.hasNext()) {
+//                             buffer.append(","); //$NON-NLS-1$
+//                     }
+//             }
+//             buffer.append("]"); //$NON-NLS-1$
+//     }
+//             
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     int memSize() {
+//             int size = BASE_NODE_SIZE + 8 * 4;
+//             if (this.lineEndTable != null) {
+//                     size += HEADERS + 4 * this.lineEndTable.length;
+//             }
+//             if (this.optionalCommentTable != null) {
+//                     size += HEADERS + 4 * this.optionalCommentTable.length;
+//             }
+//             // ignore the space taken up by optionalCommentList
+//             return size;
+//     }
+//     
+//     /* (omit javadoc for this method)
+//      * Method declared on ASTNode.
+//      */
+//     int treeSize() {
+//             int size = memSize();
+//             if (this.optionalPackageDeclaration != null) {
+//                     size += getPackage().treeSize();
+//             }
+//             size += this.imports.listSize();
+//             size += this.types.listSize();
+//             // include disconnected comments
+//             if (this.optionalCommentList != null) {
+//                     for (int i = 0; i < this.optionalCommentList.size(); i++) {
+//                             Comment comment = (Comment) this.optionalCommentList.get(i);
+//                             if (comment != null && comment.getParent() == null) {
+//                                     size += comment.treeSize();
+//                             }
+//                     }
+//             }
+//             return size;
+//     }
+//     
+//     /**
+//      * Enables the recording of changes to this compilation
+//      * unit and its descendents. The compilation unit must have
+//      * been created by <code>ASTParser</code> and still be in
+//      * its original state. Once recording is on,
+//      * arbitrary changes to the subtree rooted at this compilation
+//      * unit are recorded internally. Once the modification has
+//      * been completed, call <code>rewrite</code> to get an object
+//      * representing the corresponding edits to the original 
+//      * source code string.
+//      *
+//      * @exception IllegalArgumentException if this compilation unit is
+//      * marked as unmodifiable, or if this compilation unit has already 
+//      * been tampered with, or recording has already been enabled
+//      * @since 3.0
+//      */
+//     public void recordModifications() {
+//             getAST().recordModifications(this);
+//     }
+//     
+//     /**
+//      * Converts all modifications recorded for this compilation
+//      * unit into an object representing the corresponding text
+//      * edits to the given document containing the original source
+//      * code for this compilation unit.
+//      * <p>
+//      * The compilation unit must have been created by
+//      * <code>ASTParser</code> from the source code string in the
+//      * given document, and recording must have been turned
+//      * on with a prior call to <code>recordModifications</code>
+//      * while the AST was still in its original state.
+//      * </p>
+//      * <p>
+//      * Calling this methods does not discard the modifications
+//      * on record. Subsequence modifications made to the AST
+//      * are added to the ones already on record. If this method
+//      * is called again later, the resulting text edit object will
+//      * accurately reflect the net cumulative affect of all those
+//      * changes.
+//      * </p>
+//      * 
+//      * @param document original document containing source code
+//      * for this compilation unit
+//      * @param options the table of formatter options
+//      * (key type: <code>String</code>; value type: <code>String</code>);
+//      * or <code>null</code> to use the standard global options
+//      * {@link JavaCore#getOptions() JavaCore.getOptions()}.
+//      * @return text edit object describing the changes to the
+//      * document corresponding to the recorded AST modifications
+//      * @exception IllegalArgumentException if the document passed is
+//      * <code>null</code> or does not correspond to this AST
+//      * @exception IllegalStateException if <code>recordModifications</code>
+//      * was not called to enable recording
+//      * @see #recordModifications()
+//      * @since 3.0
+//      */
+//     public TextEdit rewrite(IDocument document, Map options) {
+//             return getAST().rewrite(document, options);
+//     }
+}
+
index 0e61752..fdc8bbd 100644 (file)
@@ -10,9 +10,9 @@
  *******************************************************************************/
 package net.sourceforge.phpdt.core.jdom;
 
-import net.sourceforge.phpdt.internal.core.Util;
 import net.sourceforge.phpdt.internal.core.jdom.DOMBuilder;
 import net.sourceforge.phpdt.internal.core.jdom.SimpleDOMBuilder;
+import net.sourceforge.phpdt.internal.core.util.Util;
 
 
 /**
index 3a40512..5ee16b9 100644 (file)
@@ -19,8 +19,7 @@ import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 
 /**
- * @author jsurfer
- *
+ * 
  * 
  */
 public class UnitParser extends Parser {
@@ -202,7 +201,7 @@ public class UnitParser extends Parser {
             new Integer(problem.getSourceStart()),
             new Integer(problem.getSourceEnd() + 1),
             new Integer(problem.getSourceLineNumber()),
-            net.sourceforge.phpdt.internal.core.Util.getProblemArgumentsForMarker(problem.getArguments())});
+            net.sourceforge.phpdt.internal.core.util.Util.getProblemArgumentsForMarker(problem.getArguments())});
       }
 
     }
index 9ece7dc..66208c0 100644 (file)
@@ -24,6 +24,7 @@ import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
 
 public class Util {
 
@@ -373,15 +374,16 @@ public class Util {
         * implementation is not creating extra strings.
         */
        public final static boolean isJavaFileName(String name) {
-               int nameLength = name == null ? 0 : name.length();
-               int suffixLength = SUFFIX_JAVA.length;
-               if (nameLength < suffixLength) return false;
-
-               for (int i = 0; i < suffixLength; i++) {
-                       char c = name.charAt(nameLength - i - 1);
-                       int suffixIndex = suffixLength - i - 1;
-                       if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false;
-               }
-               return true;            
+               return PHPFileUtil.isPHPFileName(name);
+//             int nameLength = name == null ? 0 : name.length();
+//             int suffixLength = SUFFIX_JAVA.length;
+//             if (nameLength < suffixLength) return false;
+//
+//             for (int i = 0; i < suffixLength; i++) {
+//                     char c = name.charAt(nameLength - i - 1);
+//                     int suffixIndex = suffixLength - i - 1;
+//                     if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false;
+//             }
+//             return true;            
        }
 }
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java
new file mode 100644 (file)
index 0000000..ea8125b
--- /dev/null
@@ -0,0 +1,1365 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.core.PackageFragmentRoot;
+import net.sourceforge.phpdt.internal.corext.Assert;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Provides convenient utility methods to other types in this package.
+ */
+public class Util {
+
+       private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+       private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+       private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
+       private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
+
+       public interface Comparable {
+               /**
+                * Returns 0 if this and c are equal, >0 if this is greater than c,
+                * or <0 if this is less than c.
+                */
+               int compareTo(Comparable c);
+       }
+
+       public interface Comparer {
+               /**
+                * Returns 0 if a and b are equal, >0 if a is greater than b,
+                * or <0 if a is less than b.
+                */
+               int compare(Object a, Object b);
+       }
+       
+       public interface Displayable {
+               String displayString(Object o);
+       }
+       
+       public static final String[] fgEmptyStringArray = new String[0];
+
+       /**
+        * Are we running JDK 1.1?
+        */
+       private static boolean JDK1_1 = false;
+
+       /* Bundle containing messages */
+       protected static ResourceBundle bundle;
+       private final static String bundleName = "net.sourceforge.phpdt.internal.core.messages"; //$NON-NLS-1$
+
+//     public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
+//     public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
+
+       static {
+               String ver = System.getProperty("java.version"); //$NON-NLS-1$
+               JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$
+               relocalize();
+       }       
+       
+       /**
+        * Lookup the message with the given ID in this catalog 
+        */
+       public static String bind(String id) {
+               return bind(id, (String[])null);
+       }
+       
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given string values.
+        */
+       public static String bind(String id, String[] bindings) {
+               if (id == null)
+                       return "No message available"; //$NON-NLS-1$
+               String message = null;
+               try {
+                       message = bundle.getString(id);
+               } catch (MissingResourceException e) {
+                       // If we got an exception looking for the message, fail gracefully by just returning
+                       // the id we were looking for.  In most cases this is semi-informative so is not too bad.
+                       return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+               }
+               // for compatibility with MessageFormat which eliminates double quotes in original message
+               char[] messageWithNoDoubleQuotes =
+               CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+               message = new String(messageWithNoDoubleQuotes);
+       
+               if (bindings == null)
+                       return message;
+       
+               int length = message.length();
+               int start = -1;
+               int end = length;
+               StringBuffer output = new StringBuffer(80);
+               while (true) {
+                       if ((end = message.indexOf('{', start)) > -1) {
+                               output.append(message.substring(start + 1, end));
+                               if ((start = message.indexOf('}', end)) > -1) {
+                                       int index = -1;
+                                       try {
+                                               index = Integer.parseInt(message.substring(end + 1, start));
+                                               output.append(bindings[index]);
+                                       } catch (NumberFormatException nfe) {
+                                               output.append(message.substring(end + 1, start + 1));
+                                       } catch (ArrayIndexOutOfBoundsException e) {
+                                               output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+                                       }
+                               } else {
+                                       output.append(message.substring(end, length));
+                                       break;
+                               }
+                       } else {
+                               output.append(message.substring(start + 1, length));
+                               break;
+                       }
+               }
+               return output.toString();
+       }
+
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given string.
+        */
+       public static String bind(String id, String binding) {
+               return bind(id, new String[] {binding});
+       }
+       
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given strings.
+        */
+       public static String bind(String id, String binding1, String binding2) {
+               return bind(id, new String[] {binding1, binding2});
+       }
+
+       /**
+        * Checks the type signature in String sig, 
+        * starting at start and ending before end (end is not included).
+        * Returns the index of the character immediately after the signature if valid,
+        * or -1 if not valid.
+        */
+       private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
+               if (start >= end) return -1;
+               int i = start;
+               char c = sig.charAt(i++);
+               int nestingDepth = 0;
+               while (c == '[') {
+                       ++nestingDepth;
+                       if (i >= end) return -1;
+                       c = sig.charAt(i++);
+               }
+               switch (c) {
+                       case 'B':
+                       case 'C': 
+                       case 'D':
+                       case 'F':
+                       case 'I':
+                       case 'J':
+                       case 'S': 
+                       case 'Z':
+                               break;
+                       case 'V':
+                               if (!allowVoid) return -1;
+                               // array of void is not allowed
+                               if (nestingDepth != 0) return -1;
+                               break;
+                       case 'L':
+                               int semicolon = sig.indexOf(';', i);
+                               // Must have at least one character between L and ;
+                               if (semicolon <= i || semicolon >= end) return -1;
+                               i = semicolon + 1;
+                               break;
+                       default:
+                               return -1;
+               }
+               return i;
+       }
+       
+       /**
+        * Combines two hash codes to make a new one.
+        */
+       public static int combineHashCodes(int hashCode1, int hashCode2) {
+               return hashCode1 * 17 + hashCode2;
+       }
+       
+       /**
+        * Compares two byte arrays.  
+        * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
+        * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
+        * Returns 0 if they are equal or both null.
+        */
+       public static int compare(byte[] a, byte[] b) {
+               if (a == b)
+                       return 0;
+               if (a == null)
+                       return -1;
+               if (b == null)
+                       return 1;
+               int len = Math.min(a.length, b.length);
+               for (int i = 0; i < len; ++i) {
+                       int diff = a[i] - b[i];
+                       if (diff != 0)
+                               return diff;
+               }
+               if (a.length > len)
+                       return 1;
+               if (b.length > len)
+                       return -1;
+               return 0;
+       }
+
+       /**
+        * Compares two char arrays lexicographically. 
+        * The comparison is based on the Unicode value of each character in
+        * the char arrays. 
+        * @return  the value <code>0</code> if a is equal to
+        *          b; a value less than <code>0</code> if a
+        *          is lexicographically less than b; and a
+        *          value greater than <code>0</code> if a is
+        *          lexicographically greater than b.
+        */
+       public static int compare(char[] v1, char[] v2) {
+               int len1 = v1.length;
+               int len2 = v2.length;
+               int n = Math.min(len1, len2);
+               int i = 0;
+               while (n-- != 0) {
+                       if (v1[i] != v2[i]) {
+                               return v1[i] - v2[i];
+                       }
+                       ++i;
+               }
+               return len1 - len2;
+       }
+
+       /**
+        * Concatenate two strings with a char in between.
+        * @see #concat(String, String)
+        */
+       public static String concat(String s1, char c, String s2) {
+               if (s1 == null) s1 = "null"; //$NON-NLS-1$
+               if (s2 == null) s2 = "null"; //$NON-NLS-1$
+               int l1 = s1.length();
+               int l2 = s2.length();
+               char[] buf = new char[l1 + 1 + l2];
+               s1.getChars(0, l1, buf, 0);
+               buf[l1] = c;
+               s2.getChars(0, l2, buf, l1 + 1);
+               return new String(buf);
+       }
+       
+       /**
+        * Concatenate two strings.
+        * Much faster than using +, which:
+        *              - creates a StringBuffer,
+        *              - which is synchronized,
+        *              - of default size, so the resulting char array is
+        *        often larger than needed.
+        * This implementation creates an extra char array, since the
+        * String constructor copies its argument, but there's no way around this.
+        */
+       public static String concat(String s1, String s2) {
+               if (s1 == null) s1 = "null"; //$NON-NLS-1$
+               if (s2 == null) s2 = "null"; //$NON-NLS-1$
+               int l1 = s1.length();
+               int l2 = s2.length();
+               char[] buf = new char[l1 + l2];
+               s1.getChars(0, l1, buf, 0);
+               s2.getChars(0, l2, buf, l1);
+               return new String(buf);
+       }
+
+       /**
+        * Concatenate three strings.
+        * @see #concat(String, String)
+        */
+       public static String concat(String s1, String s2, String s3) {
+               if (s1 == null) s1 = "null"; //$NON-NLS-1$
+               if (s2 == null) s2 = "null"; //$NON-NLS-1$
+               if (s3 == null) s3 = "null"; //$NON-NLS-1$
+               int l1 = s1.length();
+               int l2 = s2.length();
+               int l3 = s3.length();
+               char[] buf = new char[l1 + l2 + l3];
+               s1.getChars(0, l1, buf, 0);
+               s2.getChars(0, l2, buf, l1);
+               s3.getChars(0, l3, buf, l1 + l2);
+               return new String(buf);
+       }
+       
+       /**
+        * Converts a type signature from the IBinaryType representation to the DC representation.
+        */
+       public static String convertTypeSignature(char[] sig) {
+               return new String(sig).replace('/', '.');
+       }
+
+       /**
+        * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
+        * implementation is not creating extra strings.
+        */
+       public final static boolean endsWithIgnoreCase(String str, String end) {
+               
+               int strLength = str == null ? 0 : str.length();
+               int endLength = end == null ? 0 : end.length();
+               
+               // return false if the string is smaller than the end.
+               if(endLength > strLength)
+                       return false;
+                       
+               // return false if any character of the end are
+               // not the same in lower case.
+               for(int i = 1 ; i <= endLength; i++){
+                       if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
+                               return false;
+               }
+               
+               return true;
+       }
+
+       /**
+        * Compares two arrays using equals() on the elements.
+        * Either or both arrays may be null.
+        * Returns true if both are null.
+        * Returns false if only one is null.
+        * If both are arrays, returns true iff they have the same length and
+        * all elements are equal.
+        */
+       public static boolean equalArraysOrNull(int[] a, int[] b) {
+               if (a == b)
+                       return true;
+               if (a == null || b == null)
+                       return false;
+               int len = a.length;
+               if (len != b.length)
+                       return false;
+               for (int i = 0; i < len; ++i) {
+                       if (a[i] != b[i])
+                               return false;
+               }
+               return true;
+       }
+
+       /**
+        * Compares two arrays using equals() on the elements.
+        * Either or both arrays may be null.
+        * Returns true if both are null.
+        * Returns false if only one is null.
+        * If both are arrays, returns true iff they have the same length and
+        * all elements compare true with equals.
+        */
+       public static boolean equalArraysOrNull(Object[] a, Object[] b) {
+               if (a == b)     return true;
+               if (a == null || b == null) return false;
+
+               int len = a.length;
+               if (len != b.length) return false;
+               for (int i = 0; i < len; ++i) {
+                       if (a[i] == null) {
+                               if (b[i] != null) return false;
+                       } else {
+                               if (!a[i].equals(b[i])) return false;
+                       }
+               }
+               return true;
+       }
+       
+       /**
+        * Compares two String arrays using equals() on the elements.
+        * The arrays are first sorted.
+        * Either or both arrays may be null.
+        * Returns true if both are null.
+        * Returns false if only one is null.
+        * If both are arrays, returns true iff they have the same length and
+        * iff, after sorting both arrays, all elements compare true with equals.
+        * The original arrays are left untouched.
+        */
+       public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
+               if (a == b)     return true;
+               if (a == null || b == null) return false;
+               int len = a.length;
+               if (len != b.length) return false;
+               if (len >= 2) {  // only need to sort if more than two items
+                       a = sortCopy(a);
+                       b = sortCopy(b);
+               }
+               for (int i = 0; i < len; ++i) {
+                       if (!a[i].equals(b[i])) return false;
+               }
+               return true;
+       }
+       
+       /**
+        * Compares two arrays using equals() on the elements.
+        * The arrays are first sorted.
+        * Either or both arrays may be null.
+        * Returns true if both are null.
+        * Returns false if only one is null.
+        * If both are arrays, returns true iff they have the same length and
+        * iff, after sorting both arrays, all elements compare true with equals.
+        * The original arrays are left untouched.
+        */
+       public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
+               if (a == b)     return true;
+               if (a == null || b == null) return false;
+               int len = a.length;
+               if (len != b.length) return false;
+               if (len >= 2) {  // only need to sort if more than two items
+                       a = sortCopy(a);
+                       b = sortCopy(b);
+               }
+               for (int i = 0; i < len; ++i) {
+                       if (!a[i].equals(b[i])) return false;
+               }
+               return true;
+       }
+       
+       /**
+        * Compares two objects using equals().
+        * Either or both array may be null.
+        * Returns true if both are null.
+        * Returns false if only one is null.
+        * Otherwise, return the result of comparing with equals().
+        */
+       public static boolean equalOrNull(Object a, Object b) {
+               if (a == b) {
+                       return true;
+               }
+               if (a == null || b == null) {
+                       return false;
+               }
+               return a.equals(b);
+       }
+       
+       /**
+        * Given a qualified name, extract the last component.
+        * If the input is not qualified, the same string is answered.
+        */
+       public static String extractLastName(String qualifiedName) {
+               int i = qualifiedName.lastIndexOf('.');
+               if (i == -1) return qualifiedName;
+               return qualifiedName.substring(i+1);
+       }
+       
+       /**
+        * Extracts the parameter types from a method signature.
+        */
+       public static String[] extractParameterTypes(char[] sig) {
+               int count = getParameterCount(sig);
+               String[] result = new String[count];
+               if (count == 0)
+                       return result;
+               int i = CharOperation.indexOf('(', sig) + 1;
+               count = 0;
+               int len = sig.length;
+               int start = i;
+               for (;;) {
+                       if (i == len)
+                               break;
+                       char c = sig[i];
+                       if (c == ')')
+                               break;
+                       if (c == '[') {
+                               ++i;
+                       } else
+                               if (c == 'L') {
+                                       i = CharOperation.indexOf(';', sig, i + 1) + 1;
+                                       Assert.isTrue(i != 0);
+                                       result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+                                       start = i;
+                               } else {
+                                       ++i;
+                                       result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+                                       start = i;
+                               }
+               }
+               return result;
+       }
+
+       /**
+        * Extracts the return type from a method signature.
+        */
+       public static String extractReturnType(String sig) {
+               int i = sig.lastIndexOf(')');
+               Assert.isTrue(i != -1);
+               return sig.substring(i+1);      
+       }
+       
+       /**
+        * Finds the first line separator used by the given text.
+        *
+        * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>,
+        *                      or <code>null</code> if none found
+        */
+       public static String findLineSeparator(char[] text) {
+               // find the first line separator
+               int length = text.length;
+               if (length > 0) {
+                       char nextChar = text[0];
+                       for (int i = 0; i < length; i++) {
+                               char currentChar = nextChar;
+                               nextChar = i < length-1 ? text[i+1] : ' ';
+                               switch (currentChar) {
+                                       case '\n': return "\n"; //$NON-NLS-1$
+                                       case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
+                               }
+                       }
+               }
+               // not found
+               return null;
+       }
+       
+       /**
+        * Returns the line separator used by the given buffer.
+        * Uses the given text if none found.
+        *
+        * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>
+        */
+       private static String getLineSeparator(char[] text, char[] buffer) {
+               // search in this buffer's contents first
+               String lineSeparator = findLineSeparator(buffer);
+               if (lineSeparator == null) {
+                       // search in the given text
+                       lineSeparator = findLineSeparator(text);
+                       if (lineSeparator == null) {
+                               // default to system line separator
+                               return System.getProperty("line.separator");
+                       }
+               }
+               return lineSeparator;
+       }
+               
+       /**
+        * Returns the number of parameter types in a method signature.
+        */
+       public static int getParameterCount(char[] sig) {
+               int i = CharOperation.indexOf('(', sig) + 1;
+               Assert.isTrue(i != 0);
+               int count = 0;
+               int len = sig.length;
+               for (;;) {
+                       if (i == len)
+                               break;
+                       char c = sig[i];
+                       if (c == ')')
+                               break;
+                       if (c == '[') {
+                               ++i;
+                       } else
+                               if (c == 'L') {
+                                       ++count;
+                                       i = CharOperation.indexOf(';', sig, i + 1) + 1;
+                                       Assert.isTrue(i != 0);
+                               } else {
+                                       ++count;
+                                       ++i;
+                               }
+               }
+               return count;
+       }
+       
+       /**
+        * Returns the given file's contents as a byte array.
+        */
+       public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
+               InputStream stream= null;
+               try {
+                       stream = new BufferedInputStream(file.getContents(true));
+               } catch (CoreException e) {
+                       throw new JavaModelException(e);
+               }
+               try {
+                       return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+               } catch (IOException e) {
+                       throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+               } finally {
+                       try {
+                               stream.close();
+                       } catch (IOException e) {
+                       }
+               }
+       }
+       
+       /**
+        * Returns the given file's contents as a character array.
+        */
+       public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
+               String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true);
+               return getResourceContentsAsCharArray(file, encoding);
+       }
+
+       public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
+               InputStream stream= null;
+               try {
+                       stream = new BufferedInputStream(file.getContents(true));
+               } catch (CoreException e) {
+                       throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
+               }
+               try {
+                       return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
+               } catch (IOException e) {
+                       throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+               } finally {
+                       try {
+                               stream.close();
+                       } catch (IOException e) {
+                       }
+               }
+       }
+       
+       /**
+        * Returns a trimmed version the simples names returned by Signature.
+        */
+       public static String[] getTrimmedSimpleNames(String name) {
+               String[] result = Signature.getSimpleNames(name);
+               if (result == null) return null;
+               for (int i = 0, length = result.length; i < length; i++) {
+                       result[i] = result[i].trim();
+               }
+               return result;
+       }
+       
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".class")
+        * implementation is not creating extra strings.
+        */
+//     public final static boolean isClassFileName(String name) {
+//             int nameLength = name == null ? 0 : name.length();
+//             int suffixLength = SUFFIX_CLASS.length;
+//             if (nameLength < suffixLength) return false;
+//
+//             for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+//                     char c = name.charAt(offset + i);
+//                     if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+//             }
+//             return true;            
+//     }
+       
+       /*
+        * Returns whether the given java element is exluded from its root's classpath.
+        */
+       public static final boolean isExcluded(IJavaElement element) {
+               int elementType = element.getElementType();
+       PackageFragmentRoot root = null;
+       IResource resource = null;
+               switch (elementType) {
+//                     case IJavaElement.PACKAGE_FRAGMENT:
+//                             PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+//                             IResource resource = element.getResource();
+//                             return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars());
+                       case IJavaElement.COMPILATION_UNIT:
+                               root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+                               resource = element.getResource();
+//                             if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()))
+//                                     return true;
+                               return isExcluded(element.getParent());
+                       default:
+                               IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
+                               return cu != null && isExcluded(cu);
+               }
+       }
+       /*
+        * Returns whether the given resource path matches one of the exclusion
+        * patterns.
+        * 
+        * @see IClasspathEntry#getExclusionPatterns
+        */
+       public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
+               if (exclusionPatterns == null) return false;
+               char[] path = resourcePath.toString().toCharArray();
+               for (int i = 0, length = exclusionPatterns.length; i < length; i++)
+                       if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
+                               return true;
+               return false;
+       }       
+       
+       /*
+        * Returns whether the given resource matches one of the exclusion patterns.
+        * 
+        * @see IClasspathEntry#getExclusionPatterns
+        */
+       public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
+               IPath path = resource.getFullPath();
+               // ensure that folders are only excluded if all of their children are excluded
+               if (resource.getType() == IResource.FOLDER)
+                       path = path.append("*"); //$NON-NLS-1$
+               return isExcluded(path, exclusionPatterns);
+       }
+
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip")
+        * implementation is not creating extra strings.
+        */
+//     public final static boolean isArchiveFileName(String name) {
+//             int nameLength = name == null ? 0 : name.length();
+//             int suffixLength = SUFFIX_JAR.length;
+//             if (nameLength < suffixLength) return false;
+//
+//             int i, offset;
+//             for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+//                     char c = name.charAt(offset + i);
+//                     if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break;
+//             }
+//             if (i == suffixLength) return true;             
+//             for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+//                     char c = name.charAt(offset + i);
+//                     if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false;
+//             }
+//             return true;
+//     }
+       
+       /**
+        * Validate the given compilation unit name.
+        * A compilation unit name must obey the following rules:
+        * <ul>
+        * <li> it must not be null
+        * <li> it must include the <code>".java"</code> suffix
+        * <li> its prefix must be a valid identifier
+        * </ul>
+        * </p>
+        * @param name the name of a compilation unit
+        * @return a status object with code <code>IStatus.OK</code> if
+        *              the given name is valid as a compilation unit name, otherwise a status 
+        *              object indicating what is wrong with the name
+        */
+       public static boolean isValidCompilationUnitName(String name) {
+               return PHPFileUtil.isPHPFileName(name);
+//             return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
+       }
+
+       /**
+        * Validate the given .class file name.
+        * A .class file name must obey the following rules:
+        * <ul>
+        * <li> it must not be null
+        * <li> it must include the <code>".class"</code> suffix
+        * <li> its prefix must be a valid identifier
+        * </ul>
+        * </p>
+        * @param name the name of a .class file
+        * @return a status object with code <code>IStatus.OK</code> if
+        *              the given name is valid as a .class file name, otherwise a status 
+        *              object indicating what is wrong with the name
+        */
+//     public static boolean isValidClassFileName(String name) {
+//             return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
+//     }
+
+       /**
+        * Returns true if the given method signature is valid,
+        * false if it is not.
+        */
+       public static boolean isValidMethodSignature(String sig) {
+               int len = sig.length();
+               if (len == 0) return false;
+               int i = 0;
+               char c = sig.charAt(i++);
+               if (c != '(') return false;
+               if (i >= len) return false;
+               while (sig.charAt(i) != ')') {
+                       // Void is not allowed as a parameter type.
+                       i = checkTypeSignature(sig, i, len, false);
+                       if (i == -1) return false;
+                       if (i >= len) return false;
+               }
+               ++i;
+               i = checkTypeSignature(sig, i, len, true);
+               return i == len;
+       }
+       
+       /**
+        * Returns true if the given type signature is valid,
+        * false if it is not.
+        */
+       public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
+               int len = sig.length();
+               return checkTypeSignature(sig, 0, len, allowVoid) == len;
+       }
+       
+       /**
+        * Returns true if the given folder name is valid for a package,
+        * false if it is not.
+        */
+       public static boolean isValidFolderNameForPackage(String folderName) {
+//             return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
+         return true;
+       }       
+
+       /*
+        * Add a log entry
+        */
+       public static void log(Throwable e, String message) {
+               Throwable nestedException;
+               if (e instanceof JavaModelException 
+                               && (nestedException = ((JavaModelException)e).getException()) != null) {
+                       e = nestedException;
+               }
+               IStatus status= new Status(
+                       IStatus.ERROR, 
+                       JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), 
+                       IStatus.ERROR, 
+                       message, 
+                       e); 
+               JavaCore.getPlugin().getLog().log(status);
+       }       
+       
+       /**
+        * Normalizes the cariage returns in the given text.
+        * They are all changed  to use the given buffer's line separator.
+        */
+       public static char[] normalizeCRs(char[] text, char[] buffer) {
+               CharArrayBuffer result = new CharArrayBuffer();
+               int lineStart = 0;
+               int length = text.length;
+               if (length == 0) return text;
+               String lineSeparator = getLineSeparator(text, buffer);
+               char nextChar = text[0];
+               for (int i = 0; i < length; i++) {
+                       char currentChar = nextChar;
+                       nextChar = i < length-1 ? text[i+1] : ' ';
+                       switch (currentChar) {
+                               case '\n':
+                                       int lineLength = i-lineStart;
+                                       char[] line = new char[lineLength];
+                                       System.arraycopy(text, lineStart, line, 0, lineLength);
+                                       result.append(line);
+                                       result.append(lineSeparator);
+                                       lineStart = i+1;
+                                       break;
+                               case '\r':
+                                       lineLength = i-lineStart;
+                                       if (lineLength >= 0) {
+                                               line = new char[lineLength];
+                                               System.arraycopy(text, lineStart, line, 0, lineLength);
+                                               result.append(line);
+                                               result.append(lineSeparator);
+                                               if (nextChar == '\n') {
+                                                       nextChar = ' ';
+                                                       lineStart = i+2;
+                                               } else {
+                                                       // when line separator are mixed in the same file
+                                                       // \r might not be followed by a \n. If not, we should increment
+                                                       // lineStart by one and not by two.
+                                                       lineStart = i+1;
+                                               }
+                                       } else {
+                                               // when line separator are mixed in the same file
+                                               // we need to prevent NegativeArraySizeException
+                                               lineStart = i+1;
+                                       }
+                                       break;
+                       }
+               }
+               char[] lastLine;
+               if (lineStart > 0) {
+                       int lastLineLength = length-lineStart;
+                       if (lastLineLength > 0) {
+                               lastLine = new char[lastLineLength];
+                               System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
+                               result.append(lastLine);
+                       }
+                       return result.getContents();
+               } else {
+                       return text;
+               }
+       }
+
+       /**
+        * Normalizes the cariage returns in the given text.
+        * They are all changed  to use given buffer's line sepatator.
+        */
+       public static String normalizeCRs(String text, String buffer) {
+               return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
+       }
+
+       /**
+        * Sort the objects in the given collection using the given sort order.
+        */
+       private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
+               int original_left = left;
+               int original_right = right;
+               int mid = sortOrder[ (left + right) / 2];
+               do {
+                       while (sortOrder[left] < mid) {
+                               left++;
+                       }
+                       while (mid < sortOrder[right]) {
+                               right--;
+                       }
+                       if (left <= right) {
+                               Object tmp = sortedCollection[left];
+                               sortedCollection[left] = sortedCollection[right];
+                               sortedCollection[right] = tmp;
+                               int tmp2 = sortOrder[left];
+                               sortOrder[left] = sortOrder[right];
+                               sortOrder[right] = tmp2;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right) {
+                       quickSort(sortedCollection, original_left, right, sortOrder);
+               }
+               if (left < original_right) {
+                       quickSort(sortedCollection, left, original_right, sortOrder);
+               }
+       }
+
+       /**
+        * Sort the objects in the given collection using the given comparer.
+        */
+       private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
+               int original_left = left;
+               int original_right = right;
+               Object mid = sortedCollection[ (left + right) / 2];
+               do {
+                       while (comparer.compare(sortedCollection[left], mid) < 0) {
+                               left++;
+                       }
+                       while (comparer.compare(mid, sortedCollection[right]) < 0) {
+                               right--;
+                       }
+                       if (left <= right) {
+                               Object tmp = sortedCollection[left];
+                               sortedCollection[left] = sortedCollection[right];
+                               sortedCollection[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right) {
+                       quickSort(sortedCollection, original_left, right, comparer);
+               }
+               if (left < original_right) {
+                       quickSort(sortedCollection, left, original_right, comparer);
+               }
+       }
+
+       /**
+        * Sort the strings in the given collection.
+        */
+       private static void quickSort(String[] sortedCollection, int left, int right) {
+               int original_left = left;
+               int original_right = right;
+               String mid = sortedCollection[ (left + right) / 2];
+               do {
+                       while (sortedCollection[left].compareTo(mid) < 0) {
+                               left++;
+                       }
+                       while (mid.compareTo(sortedCollection[right]) < 0) {
+                               right--;
+                       }
+                       if (left <= right) {
+                               String tmp = sortedCollection[left];
+                               sortedCollection[left] = sortedCollection[right];
+                               sortedCollection[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right) {
+                       quickSort(sortedCollection, original_left, right);
+               }
+               if (left < original_right) {
+                       quickSort(sortedCollection, left, original_right);
+               }
+       }
+
+       /**
+        * Converts the given relative path into a package name.
+        * Returns null if the path is not a valid package name.
+        */
+       public static String packageName(IPath pkgPath) {
+               StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
+               for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
+                       String segment = pkgPath.segment(j);
+                       if (!isValidFolderNameForPackage(segment)) {
+                               return null;
+                       }
+                       pkgName.append(segment);
+                       if (j < pkgPath.segmentCount() - 1) {
+                               pkgName.append("." ); //$NON-NLS-1$
+                       }
+               }
+               return pkgName.toString();
+       }
+
+       /**
+        * Sort the comparable objects in the given collection.
+        */
+       private static void quickSort(Comparable[] sortedCollection, int left, int right) {
+               int original_left = left;
+               int original_right = right;
+               Comparable mid = sortedCollection[ (left + right) / 2];
+               do {
+                       while (sortedCollection[left].compareTo(mid) < 0) {
+                               left++;
+                       }
+                       while (mid.compareTo(sortedCollection[right]) < 0) {
+                               right--;
+                       }
+                       if (left <= right) {
+                               Comparable tmp = sortedCollection[left];
+                               sortedCollection[left] = sortedCollection[right];
+                               sortedCollection[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right) {
+                       quickSort(sortedCollection, original_left, right);
+               }
+               if (left < original_right) {
+                       quickSort(sortedCollection, left, original_right);
+               }
+       }
+
+       /**
+        * Sort the strings in the given collection in reverse alphabetical order.
+        */
+       private static void quickSortReverse(String[] sortedCollection, int left, int right) {
+               int original_left = left;
+               int original_right = right;
+               String mid = sortedCollection[ (left + right) / 2];
+               do {
+                       while (sortedCollection[left].compareTo(mid) > 0) {
+                               left++;
+                       }
+                       while (mid.compareTo(sortedCollection[right]) > 0) {
+                               right--;
+                       }
+                       if (left <= right) {
+                               String tmp = sortedCollection[left];
+                               sortedCollection[left] = sortedCollection[right];
+                               sortedCollection[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right) {
+                       quickSortReverse(sortedCollection, original_left, right);
+               }
+               if (left < original_right) {
+                       quickSortReverse(sortedCollection, left, original_right);
+               }
+       }
+
+       /**
+        * Sorts an array of objects in place, using the sort order given for each item.
+        */
+       public static void sort(Object[] objects, int[] sortOrder) {
+               if (objects.length > 1)
+                       quickSort(objects, 0, objects.length - 1, sortOrder);
+       }
+
+       /**
+        * Sorts an array of objects in place.
+        * The given comparer compares pairs of items.
+        */
+       public static void sort(Object[] objects, Comparer comparer) {
+               if (objects.length > 1)
+                       quickSort(objects, 0, objects.length - 1, comparer);
+       }
+
+       /**
+        * Sorts an array of strings in place using quicksort.
+        */
+       public static void sort(String[] strings) {
+               if (strings.length > 1)
+                       quickSort(strings, 0, strings.length - 1);
+       }
+
+       /**
+        * Sorts an array of Comparable objects in place.
+        */
+       public static void sort(Comparable[] objects) {
+               if (objects.length > 1)
+                       quickSort(objects, 0, objects.length - 1);
+       }
+
+       /**
+        * Sorts an array of Strings, returning a new array
+        * with the sorted items.  The original array is left untouched.
+        */
+       public static Object[] sortCopy(Object[] objects, Comparer comparer) {
+               int len = objects.length;
+               Object[] copy = new Object[len];
+               System.arraycopy(objects, 0, copy, 0, len);
+               sort(copy, comparer);
+               return copy;
+       }
+
+       /**
+        * Sorts an array of Strings, returning a new array
+        * with the sorted items.  The original array is left untouched.
+        */
+       public static String[] sortCopy(String[] objects) {
+               int len = objects.length;
+               String[] copy = new String[len];
+               System.arraycopy(objects, 0, copy, 0, len);
+               sort(copy);
+               return copy;
+       }
+
+       /**
+        * Sorts an array of Comparable objects, returning a new array
+        * with the sorted items.  The original array is left untouched.
+        */
+       public static Comparable[] sortCopy(Comparable[] objects) {
+               int len = objects.length;
+               Comparable[] copy = new Comparable[len];
+               System.arraycopy(objects, 0, copy, 0, len);
+               sort(copy);
+               return copy;
+       }
+
+       /**
+        * Sorts an array of strings in place using quicksort
+        * in reverse alphabetical order.
+        */
+       public static void sortReverseOrder(String[] strings) {
+               if (strings.length > 1)
+                       quickSortReverse(strings, 0, strings.length - 1);
+       }
+
+       /**
+        * Converts a String[] to char[][].
+        */
+       public static char[][] toCharArrays(String[] a) {
+               int len = a.length;
+               char[][] result = new char[len][];
+               for (int i = 0; i < len; ++i) {
+                       result[i] = toChars(a[i]);
+               }
+               return result;
+       }
+
+       /**
+        * Converts a String to char[].
+        */
+       public static char[] toChars(String s) {
+               int len = s.length();
+               char[] chars = new char[len];
+               s.getChars(0, len, chars, 0);
+               return chars;
+       }
+
+       /**
+        * Converts a String to char[][], where segments are separate by '.'.
+        */
+       public static char[][] toCompoundChars(String s) {
+               int len = s.length();
+               if (len == 0) {
+                       return CharOperation.NO_CHAR_CHAR;
+               }
+               int segCount = 1;
+               for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
+                       ++segCount;
+               }
+               char[][] segs = new char[segCount][];
+               int start = 0;
+               for (int i = 0; i < segCount; ++i) {
+                       int dot = s.indexOf('.', start);
+                       int end = (dot == -1 ? s.length() : dot);
+                       segs[i] = new char[end - start];
+                       s.getChars(start, end, segs[i], 0);
+                       start = end + 1;
+               }
+               return segs;
+       }
+
+       /**
+        * Converts a char[][] to String, where segments are separated by '.'.
+        */
+       public static String toString(char[][] c) {
+               StringBuffer sb = new StringBuffer();
+               for (int i = 0, max = c.length; i < max; ++i) {
+                       if (i != 0) sb.append('.');
+                       sb.append(c[i]);
+               }
+               return sb.toString();
+       }
+
+       /**
+        * Converts a char[][] and a char[] to String, where segments are separated by '.'.
+        */
+       public static String toString(char[][] c, char[] d) {
+               if (c == null) return new String(d);
+               StringBuffer sb = new StringBuffer();
+               for (int i = 0, max = c.length; i < max; ++i) {
+                       sb.append(c[i]);
+                       sb.append('.');
+               }
+               sb.append(d);
+               return sb.toString();
+       }
+
+       /**
+        * Converts a char[] to String.
+        */
+       public static String toString(char[] c) {
+               return new String(c);
+       }
+
+       /**
+        * Converts an array of Objects into String.
+        */
+       public static String toString(Object[] objects) {
+               return toString(objects, 
+                       new Displayable(){ 
+                               public String displayString(Object o) { 
+                                       if (o == null) return "null"; //$NON-NLS-1$
+                                       return o.toString(); 
+                               }
+                       });
+       }
+
+       /**
+        * Converts an array of Objects into String.
+        */
+       public static String toString(Object[] objects, Displayable renderer) {
+               if (objects == null) return ""; //$NON-NLS-1$
+               StringBuffer buffer = new StringBuffer(10);
+               for (int i = 0; i < objects.length; i++){
+                       if (i > 0) buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(renderer.displayString(objects[i]));
+               }
+               return buffer.toString();
+       }
+       
+       /**
+        * Asserts that the given method signature is valid.
+        */
+       public static void validateMethodSignature(String sig) {
+               Assert.isTrue(isValidMethodSignature(sig));
+       }
+
+       /**
+        * Asserts that the given type signature is valid.
+        */
+       public static void validateTypeSignature(String sig, boolean allowVoid) {
+               Assert.isTrue(isValidTypeSignature(sig, allowVoid));
+       }
+       public static void verbose(String log) {
+               verbose(log, System.out);
+       }
+       public static synchronized void verbose(String log, PrintStream printStream) {
+               int start = 0;
+               do {
+                       int end = log.indexOf('\n', start);
+                       printStream.print(Thread.currentThread());
+                       printStream.print(" "); //$NON-NLS-1$
+                       printStream.print(log.substring(start, end == -1 ? log.length() : end+1));
+                       start = end+1;
+               } while (start != 0);
+               printStream.println();
+       }
+       /**
+        * Creates a NLS catalog for the given locale.
+        */
+       public static void relocalize() {
+               try {
+                       bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+               } catch(MissingResourceException e) {
+                       System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+                       throw e;
+               }
+       }
+       
+       /**
+        * Put all the arguments in one String.
+        */
+       public static String getProblemArgumentsForMarker(String[] arguments){
+               StringBuffer args = new StringBuffer(10);
+               
+               args.append(arguments.length);
+               args.append(':');
+               
+                       
+               for (int j = 0; j < arguments.length; j++) {
+                       if(j != 0)
+                               args.append(ARGUMENTS_DELIMITER);
+                       
+                       if(arguments[j].length() == 0) {
+                               args.append(EMPTY_ARGUMENT);
+                       } else {                        
+                               args.append(arguments[j]);
+                       }
+               }
+               
+               return args.toString();
+       }
+       
+       /**
+        * Separate all the arguments of a String made by getProblemArgumentsForMarker
+        */
+       public static String[] getProblemArgumentsFromMarker(String argumentsString){
+               if (argumentsString == null) return null;
+               int index = argumentsString.indexOf(':');
+               if(index == -1)
+                       return null;
+               
+               int length = argumentsString.length();
+               int numberOfArg;
+               try{
+                       numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
+               } catch (NumberFormatException e) {
+                       return null;
+               }
+               argumentsString = argumentsString.substring(index + 1, length);
+               
+               String[] args = new String[length];
+               int count = 0;
+               
+               StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
+               while(tokenizer.hasMoreTokens()) {
+                       String argument = tokenizer.nextToken();
+                       if(argument.equals(EMPTY_ARGUMENT))
+                               argument = "";  //$NON-NLS-1$
+                       args[count++] = argument;
+               }
+               
+               if(count != numberOfArg)
+                       return null;
+               
+               System.arraycopy(args, 0, args = new String[count], 0, count);
+               return args;
+       }
+       
+}
index ab30dd3..3ddf18f 100644 (file)
@@ -22,11 +22,16 @@ import javax.xml.parsers.ParserConfigurationException;
 
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.Serializer;
-import org.apache.xml.serialize.SerializerFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IStatus;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Document;
 import org.w3c.dom.NamedNodeMap;
@@ -218,16 +223,27 @@ public class TemplateSet {
         node.appendChild(pattern);
       }
 
-      OutputFormat format = new OutputFormat();
-      format.setPreserveSpace(true);
-      Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format); //$NON-NLS-1$
-      serializer.asDOMSerializer().serialize(document);
+      Transformer transformer=TransformerFactory.newInstance().newTransformer();
+         transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+         transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+         DOMSource source = new DOMSource(document);
+         StreamResult result = new StreamResult(stream);
+
+         transformer.transform(source, result);
+      
+//      OutputFormat format = new OutputFormat();
+//      format.setPreserveSpace(true);
+//      Serializer serializer = SerializerFactory.getSerializerFactory("xml").makeSerializer(stream, format); //$NON-NLS-1$
+//      serializer.asDOMSerializer().serialize(document);
 
     } catch (ParserConfigurationException e) {
       throwWriteException(e);
-    } catch (IOException e) {
-      throwWriteException(e);
-    }
+    } catch (TransformerException e) {
+               throwWriteException(e);
+       }
+//    } catch (IOException e) {
+//      throwWriteException(e);
+//    }
   }
 
   private static void throwReadException(Throwable t) throws CoreException {
index 120b578..3a0465f 100644 (file)
@@ -41,7 +41,15 @@ public class ActionMessages {
                        return '!' + key + '!';
                }
        }
-       
+       /**
+        * Returns the resource bundle managed by the receiver.
+        * 
+        * @return the resource bundle
+        * @since 3.0
+        */
+       public static ResourceBundle getResourceBundle() {
+               return RESOURCE_BUNDLE;
+       }
        /**
         * Returns the formatted resource string associated with the given key in the resource bundle. 
         * <code>MessageFormat</code> is used to format the message. If there isn't  any value 
index 1567bca..2da463d 100644 (file)
@@ -53,7 +53,7 @@ public class AddBlockCommentAction extends BlockCommentAction {
                int selectionOffset= selection.getOffset();
                int selectionEndOffset= selectionOffset + selection.getLength();
                List edits= new LinkedList();
-               ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, selectionOffset);
+               ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, selectionOffset, false);
 
                handleFirstPartition(partition, edits, factory, selectionOffset);
 
@@ -124,7 +124,7 @@ public class AddBlockCommentAction extends BlockCommentAction {
                }
 
                // advance to next partition
-               partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset);
+               partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset, false);
                partType= partition.getType();
 
                // start of next partition
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingActionGroup.java
new file mode 100644 (file)
index 0000000..e40f478
--- /dev/null
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IMenuManager;
+
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.source.projection.IProjectionListener;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+
+/**
+ * Groups the JDT folding actions.
+ *  
+ * @since 3.0
+ */
+public class FoldingActionGroup extends ActionGroup {
+       private ProjectionViewer fViewer;
+       
+       private TextOperationAction fToggle;
+       private TextOperationAction fExpand;
+       private TextOperationAction fCollapse;
+       private TextOperationAction fExpandAll;
+
+       private IProjectionListener fProjectionListener;
+       
+       /**
+        * Creates a new projection action group for <code>editor</code>. If the
+        * supplied viewer is not an instance of <code>ProjectionViewer</code>, the
+        * action group is disabled.
+        * 
+        * @param editor the text editor to operate on
+        * @param viewer the viewer of the editor
+        */
+       public FoldingActionGroup(ITextEditor editor, ITextViewer viewer) {
+               if (viewer instanceof ProjectionViewer) {
+                       fViewer= (ProjectionViewer) viewer;
+                       
+                       fProjectionListener= new IProjectionListener() {
+
+                               public void projectionEnabled() {
+                                       update();
+                               }
+
+                               public void projectionDisabled() {
+                                       update();
+                               }
+                       };
+                       
+                       fViewer.addProjectionListener(fProjectionListener);
+                       
+                       fToggle= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$
+                       fToggle.setChecked(true);
+                       fToggle.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE);
+                       editor.setAction("FoldingToggle", fToggle); //$NON-NLS-1$
+                       
+                       fExpandAll= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$
+                       fExpandAll.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL);
+                       editor.setAction("FoldingExpandAll", fExpandAll); //$NON-NLS-1$
+                       
+                       fExpand= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Expand.", editor, ProjectionViewer.EXPAND, true); //$NON-NLS-1$
+                       fExpand.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND);
+                       editor.setAction("FoldingExpand", fExpand); //$NON-NLS-1$
+                       
+                       fCollapse= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Collapse.", editor, ProjectionViewer.COLLAPSE, true); //$NON-NLS-1$
+                       fCollapse.setActionDefinitionId(IFoldingCommandIds.FOLDING_COLLAPSE);
+                       editor.setAction("FoldingCollapse", fCollapse); //$NON-NLS-1$
+               }
+       }
+       
+       /**
+        * Returns <code>true</code> if the group is enabled. 
+        * <pre>
+        * Invariant: isEnabled() <=> fViewer and all actions are != null.
+        * </pre>
+        * 
+        * @return <code>true</code> if the group is enabled
+        */
+       protected boolean isEnabled() {
+               return fViewer != null;
+       }
+       
+       /*
+        * @see org.eclipse.ui.actions.ActionGroup#dispose()
+        */
+       public void dispose() {
+               if (isEnabled()) {
+                       fViewer.removeProjectionListener(fProjectionListener);
+                       fViewer= null;
+               }
+               super.dispose();
+       }
+       
+       /**
+        * Updates the actions.
+        */
+       protected void update() {
+               if (isEnabled()) {
+                       fToggle.update();
+                       fToggle.setChecked(fViewer.getProjectionAnnotationModel() != null);
+                       fExpand.update();
+                       fExpandAll.update();
+                       fCollapse.update();
+               }
+       }
+       
+       /**
+        * Fills the menu with all folding actions.
+        * 
+        * @param manager the menu manager for the folding submenu
+        */
+       public void fillMenu(IMenuManager manager) {
+               if (isEnabled()) {
+                       update();
+                       manager.add(fToggle);
+                       manager.add(fExpandAll);
+                       manager.add(fExpand);
+                       manager.add(fCollapse);
+               }
+       }
+       
+       /*
+        * @see org.eclipse.ui.actions.ActionGroup#updateActionBars()
+        */
+       public void updateActionBars() {
+               update();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingExpandAllRulerAction.java
new file mode 100644 (file)
index 0000000..7619360
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+
+/**
+ * Groups the JDT folding actions.
+ *  
+ * @since 3.0
+ */
+public class FoldingExpandAllRulerAction extends AbstractRulerActionDelegate {
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.IVerticalRulerInfo)
+        */
+       protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
+               TextOperationAction action= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.ExpandAll.", editor, ProjectionViewer.EXPAND_ALL, true); //$NON-NLS-1$
+               action.setActionDefinitionId(IFoldingCommandIds.FOLDING_EXPAND_ALL);
+               return action;
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/actions/FoldingToggleRulerAction.java
new file mode 100644 (file)
index 0000000..d22d55f
--- /dev/null
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.actions;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.IVerticalRulerInfo;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.editors.text.IFoldingCommandIds;
+import org.eclipse.ui.texteditor.AbstractRulerActionDelegate;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextOperationAction;
+
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+
+/**
+ * Groups the JDT folding actions.
+ *  
+ * @since 3.0
+ */
+public class FoldingToggleRulerAction extends AbstractRulerActionDelegate {
+
+       private IAction fUIAction;
+       private TextOperationAction fAction;
+       private ITextEditor fTextEditor;
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#createAction(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.IVerticalRulerInfo)
+        */
+       protected IAction createAction(ITextEditor editor, IVerticalRulerInfo rulerInfo) {
+               fTextEditor= editor;
+               fAction= new TextOperationAction(ActionMessages.getResourceBundle(), "Projection.Toggle.", editor, ProjectionViewer.TOGGLE, true); //$NON-NLS-1$
+               fAction.setActionDefinitionId(IFoldingCommandIds.FOLDING_TOGGLE);
+
+               return fAction;
+       }
+       
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart)
+        */
+       public void setActiveEditor(IAction callerAction, IEditorPart targetEditor) {
+               fUIAction= callerAction;
+               super.setActiveEditor(callerAction, targetEditor);
+       }
+       
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractRulerActionDelegate#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
+        */
+       public void menuAboutToShow(IMenuManager manager) {
+               update();
+               super.menuAboutToShow(manager);
+       }
+       
+       private void update() {
+               if (fTextEditor instanceof PHPEditor) {
+                       ISourceViewer viewer= ((PHPEditor) fTextEditor).getViewer();
+                       if (viewer instanceof ProjectionViewer) {
+                               boolean enabled= ((ProjectionViewer) viewer).getProjectionAnnotationModel() != null;
+                               fUIAction.setChecked(enabled);
+                       }
+               }
+       }
+}
index 60eadc2..2af8550 100644 (file)
@@ -54,7 +54,7 @@ public class RemoveBlockCommentAction extends BlockCommentAction {
                int offset= selection.getOffset();
                int endOffset= offset + selection.getLength();
 
-               ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, offset);
+               ITypedRegion partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, offset, false);
                int partOffset= partition.getOffset();
                int partEndOffset= partOffset + partition.getLength();
                
@@ -65,7 +65,7 @@ public class RemoveBlockCommentAction extends BlockCommentAction {
                                edits.add(factory.createEdit(partEndOffset - tokenLength, tokenLength, "")); //$NON-NLS-1$
                        }
                        
-                       partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset);
+                       partition= docExtension.getPartition(IPHPPartitions.PHP_PARTITIONING, partEndOffset, false);
                        partOffset= partition.getOffset();
                        partEndOffset= partOffset + partition.getLength();
                }
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/ITypingRunListener.java
new file mode 100644 (file)
index 0000000..0d79e10
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+
+/**
+ * Listener for <code>TypingRun</code> events.
+ * 
+ * @since 3.0
+ */
+public interface ITypingRunListener {
+       /**
+        * Called when a new <code>TypingRun</code> is started.
+        * 
+        * @param run the newly started run
+        */
+       void typingRunStarted(TypingRun run);
+       
+       /**
+        * Called whenever a <code>TypingRun</code> is ended.
+        * 
+        * @param run the ended run
+        * @param reason the type of change that caused the end of the run
+        */
+       void typingRunEnded(TypingRun run, ChangeType reason);
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/JavaPresentationReconciler.java
new file mode 100644 (file)
index 0000000..67b0c5e
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.presentation.PresentationReconciler;
+
+
+/**
+ * Presentation reconciler, adding functionality for operation without a viewer.
+ * 
+ * @since 3.0
+ */
+public class JavaPresentationReconciler extends PresentationReconciler {
+       
+       /** Last used document */
+       private IDocument fLastDocument;
+       
+       /**
+        * Constructs a "repair description" for the given damage and returns
+        * this description as a text presentation.
+        * <p>
+        * NOTE: Should not be used if this reconciler is installed on a viewer.
+        * </p>
+        *
+        * @param damage the damage to be repaired
+        * @param document the document whose presentation must be repaired
+        * @return the presentation repair description as text presentation
+        */
+       public TextPresentation createRepairDescription(IRegion damage, IDocument document) {
+               if (document != fLastDocument) {
+                       setDocumentToDamagers(document);
+                       setDocumentToRepairers(document);
+               }
+               return createPresentation(damage, document);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/PreferencesAdapter.java
new file mode 100644 (file)
index 0000000..0302dc9
--- /dev/null
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ *******************************************************************************/
+
+package net.sourceforge.phpdt.internal.ui.text;
+
+import org.eclipse.core.runtime.Preferences;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Adapts {@link org.eclipse.core.runtime.Preferences} to
+ * {@link org.eclipse.jface.preference.IPreferenceStore}
+ * 
+ * @since 3.0
+ */
+public class PreferencesAdapter implements IPreferenceStore {
+
+       /**
+        * Property change listener. Listens for events of type
+        * {@link org.eclipse.core.runtime.Preferences.PropertyChangeEvent} and fires
+        * a {@link org.eclipse.jface.util.PropertyChangeEvent} on the
+        * adapter with arguments from the received event.
+        */
+       private class PropertyChangeListener implements Preferences.IPropertyChangeListener {
+
+               /*
+                * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(org.eclipse.core.runtime.Preferences.PropertyChangeEvent)
+                */
+               public void propertyChange(Preferences.PropertyChangeEvent event) {
+                       firePropertyChangeEvent(event.getProperty(), event.getOldValue(), event.getNewValue());
+               }
+       }
+       
+       /** Listeners on the adapter */
+       private ListenerList fListeners= new ListenerList();
+       
+       /** Listener on the adapted Preferences */
+       private PropertyChangeListener fListener= new PropertyChangeListener();
+       
+       /** Adapted Preferences */
+       private Preferences fPreferences;
+
+       /** True iff no events should be forwarded */
+       private boolean fSilent;
+       
+       /**
+        * Initialize with empty Preferences.
+        */
+       public PreferencesAdapter() {
+               this(new Preferences());
+       }
+       /**
+        * Initialize with the given Preferences.
+        * 
+        * @param preferences The preferences to wrap.
+        */
+       public PreferencesAdapter(Preferences preferences) {
+               fPreferences= preferences;
+       }
+       
+       /**
+        * {@inheritDoc}
+        */
+       public void addPropertyChangeListener(IPropertyChangeListener listener) {
+               if (fListeners.size() == 0)
+                       fPreferences.addPropertyChangeListener(fListener);
+               fListeners.add(listener);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void removePropertyChangeListener(IPropertyChangeListener listener) {
+               fListeners.remove(listener);
+               if (fListeners.size() == 0)
+                       fPreferences.removePropertyChangeListener(fListener);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean contains(String name) {
+               return fPreferences.contains(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void firePropertyChangeEvent(String name, Object oldValue, Object newValue) {
+               if (!fSilent) {
+                       PropertyChangeEvent event= new PropertyChangeEvent(this, name, oldValue, newValue);
+                       Object[] listeners= fListeners.getListeners();
+                       for (int i= 0; i < listeners.length; i++)
+                               ((IPropertyChangeListener) listeners[i]).propertyChange(event);
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean getBoolean(String name) {
+               return fPreferences.getBoolean(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean getDefaultBoolean(String name) {
+               return fPreferences.getDefaultBoolean(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public double getDefaultDouble(String name) {
+               return fPreferences.getDefaultDouble(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public float getDefaultFloat(String name) {
+               return fPreferences.getDefaultFloat(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public int getDefaultInt(String name) {
+               return fPreferences.getDefaultInt(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public long getDefaultLong(String name) {
+               return fPreferences.getDefaultLong(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public String getDefaultString(String name) {
+               return fPreferences.getDefaultString(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public double getDouble(String name) {
+               return fPreferences.getDouble(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public float getFloat(String name) {
+               return fPreferences.getFloat(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public int getInt(String name) {
+               return fPreferences.getInt(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public long getLong(String name) {
+               return fPreferences.getLong(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public String getString(String name) {
+               return fPreferences.getString(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean isDefault(String name) {
+               return fPreferences.isDefault(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public boolean needsSaving() {
+               return fPreferences.needsSaving();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void putValue(String name, String value) {
+               try {
+                       fSilent= true;
+                       fPreferences.setValue(name, value);
+               } finally {
+                       fSilent= false;
+               }
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, double value) {
+               fPreferences.setDefault(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, float value) {
+               fPreferences.setDefault(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, int value) {
+               fPreferences.setDefault(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, long value) {
+               fPreferences.setDefault(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, String defaultObject) {
+               fPreferences.setDefault(name, defaultObject);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setDefault(String name, boolean value) {
+               fPreferences.setDefault(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setToDefault(String name) {
+               fPreferences.setToDefault(name);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, double value) {
+               fPreferences.setValue(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, float value) {
+               fPreferences.setValue(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, int value) {
+               fPreferences.setValue(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, long value) {
+               fPreferences.setValue(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, String value) {
+               fPreferences.setValue(name, value);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void setValue(String name, boolean value) {
+               fPreferences.setValue(name, value);
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/SmartBackspaceManager.java
new file mode 100644 (file)
index 0000000..99484ea
--- /dev/null
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.VerifyKeyListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.graphics.Point;
+
+import org.eclipse.jface.text.Assert;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension;
+import org.eclipse.jface.text.TextViewer;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+
+
+/**
+ * Installs as a verify key listener on a viewer and overwrites the behaviour
+ * of the backspace key. Clients may register undo specifications for certain
+ * offsets in a document. The <code>SmartBackspaceManager</code> will manage the
+ * specfications and execute the contained <code>TextEdit</code>s when backspace
+ * is pressed at the given offset and the specification is still valid.
+ * <p>
+ * Undo specifications are removed after a number of typing runs.
+ * </p>
+ *  
+ * @since 3.0
+ */
+public class SmartBackspaceManager {
+       /* independent of JDT - may be moved to jface.text */
+
+       /**
+        * An undo specification describes the change that should be executed if
+        * backspace is pressed at its trigger offset.
+        *  
+        * @since 3.0
+        */
+       public static final class UndoSpec {
+               private final int triggerOffset;
+               private final IRegion selection;
+               private final TextEdit[] undoEdits;
+               private final UndoSpec child;
+               int lives;
+               
+               /**
+                * Creates a new spec. A specification consists of a number of
+                * <code>TextEdit</code> s that will be executed when backspace is
+                * pressed at <code>triggerOffset</code>. The spec will be removed
+                * when it is executed, or if more than <code>lives</code>
+                * <code>TypingRun</code>s have ended after registering the spec.
+                * <p>
+                * Optionally, a child specification can be registered. After executing
+                * the spec, the child spec will be registered with the manager. This allows
+                * to create chains of <code>UndoSpec</code>s that will be executed upon
+                * repeated pressing of backspace.
+                * </p>
+                * 
+                * @param triggerOffset the offset where this spec is active
+                * @param selection the selection after executing the undo spec
+                * @param edits the <code>TextEdit</code> s to perform when executing
+                *        the spec
+                * @param lives the number of <code>TypingRun</code> s before removing
+                *        the spec
+                * @param child a child specification that will be registered after
+                *        executing this spec, or <code>null</code>
+                */
+               public UndoSpec(int triggerOffset, IRegion selection, TextEdit[] edits, int lives, UndoSpec child) {
+                       Assert.isLegal(triggerOffset >= 0);
+                       Assert.isLegal(selection != null);
+                       Assert.isLegal(lives >= 0);
+                       Assert.isLegal(edits != null);
+                       Assert.isLegal(edits.length > 0);
+                       for (int i= 0; i < edits.length; i++) {
+                               Assert.isLegal(edits[i] != null);
+                       }
+                       
+                       this.triggerOffset= triggerOffset;
+                       this.selection= selection;
+                       this.undoEdits= edits;
+                       this.lives= lives;
+                       this.child= child;
+               }
+       }
+
+
+       private class BackspaceListener implements VerifyKeyListener {
+
+               /*
+                * @see org.eclipse.swt.custom.VerifyKeyListener#verifyKey(org.eclipse.swt.events.VerifyEvent)
+                */
+               public void verifyKey(VerifyEvent event) {
+                       if (fViewer != null && isBackspace(event)) {
+                               int offset= getCaretOffset();
+                               UndoSpec spec= removeEdit(offset);
+                               if (spec != null) {
+                                       try {
+                                               beginChange();
+                                               for (int i= 0; i < spec.undoEdits.length; i++) {
+                                                       spec.undoEdits[i].apply(getDocument(), TextEdit.UPDATE_REGIONS);
+                                               }
+                                               fViewer.setSelectedRange(spec.selection.getOffset(), spec.selection.getLength());
+                                               if (spec.child != null)
+                                                       register(spec.child);
+                                       } catch (MalformedTreeException e) {
+                                               // fall back to standard bs
+                                               return;
+                                       } catch (BadLocationException e) {
+                                               // fall back to standard bs
+                                               return;
+                                       } finally {
+                                               endChange();
+                                       }
+                                       event.doit= false;
+                               }
+                               
+                       }
+               }
+
+               private void beginChange() {
+                       ITextViewer viewer= fViewer;
+                       if (viewer instanceof TextViewer) {
+                               TextViewer v= (TextViewer) viewer;
+                               v.getRewriteTarget().beginCompoundChange();
+                               v.setRedraw(false);
+                       }
+               }
+
+               private void endChange() {
+                       ITextViewer viewer= fViewer;
+                       if (viewer instanceof TextViewer) {
+                               TextViewer v= (TextViewer) viewer;
+                               v.getRewriteTarget().endCompoundChange();
+                               v.setRedraw(true);
+                       }
+               }
+
+               private boolean isBackspace(VerifyEvent event) {
+                       return event.doit == true && event.character == SWT.BS && event.stateMask == 0;
+               }
+
+               private int getCaretOffset() {
+                       ITextViewer viewer= fViewer;
+                       Point point= viewer.getSelectedRange();
+                       return point.x;
+               }
+
+       }
+       
+       private ITextViewer fViewer;
+       private BackspaceListener fBackspaceListener;
+       private Map fSpecs;
+       private TypingRunDetector fRunDetector;
+       private ITypingRunListener fRunListener;
+
+       /**
+        * Registers an undo specification with this manager.
+        * 
+        * @param spec the specification to register
+        * @throws IllegalStateException if the manager is not installed
+        */
+       public void register(UndoSpec spec) {
+               if (fViewer == null)
+                       throw new IllegalStateException();
+               
+               ensureListenerInstalled();
+               addEdit(spec);
+       }
+
+       private void addEdit(UndoSpec spec) {
+               Integer i= new Integer(spec.triggerOffset);
+               fSpecs.put(i, spec);
+       }
+       
+       private UndoSpec removeEdit(int offset) {
+               Integer i= new Integer(offset);
+               UndoSpec spec= (UndoSpec) fSpecs.remove(i);
+               return spec;
+       }
+
+       private void ensureListenerInstalled() {
+               if (fBackspaceListener == null) {
+                       fBackspaceListener= new BackspaceListener();
+                       ITextViewer viewer= fViewer;
+                       if (viewer instanceof ITextViewerExtension)
+                               ((ITextViewerExtension) viewer).prependVerifyKeyListener(fBackspaceListener);
+                       else
+                               viewer.getTextWidget().addVerifyKeyListener(fBackspaceListener);
+               }
+       }
+
+       private void ensureListenerRemoved() {
+               if (fBackspaceListener != null) {
+                       ITextViewer viewer= fViewer;
+                       if (viewer instanceof ITextViewerExtension)
+                               ((ITextViewerExtension) viewer).removeVerifyKeyListener(fBackspaceListener);
+                       else
+                               viewer.getTextWidget().removeVerifyKeyListener(fBackspaceListener);
+                       fBackspaceListener= null;
+               }
+       }
+
+       private IDocument getDocument() {
+               return fViewer.getDocument();
+       }
+
+       /**
+        * Installs the receiver on a text viewer.
+        * 
+        * @param viewer
+        */
+       public void install(ITextViewer viewer) {
+               Assert.isLegal(viewer != null);
+               
+               fViewer= viewer;
+               fSpecs= new HashMap();
+               fRunDetector= new TypingRunDetector();
+               fRunDetector.install(viewer);
+               fRunListener= new ITypingRunListener() {
+
+                       /*
+                        * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunStarted(org.eclipse.jface.text.TypingRunDetector.TypingRun)
+                        */
+                       public void typingRunStarted(TypingRun run) {
+                       }
+
+                       /*
+                        * @see org.eclipse.jface.text.TypingRunDetector.ITypingRunListener#typingRunEnded(org.eclipse.jface.text.TypingRunDetector.TypingRun)
+                        */
+                       public void typingRunEnded(TypingRun run, ChangeType reason) {
+                               if (reason == TypingRun.SELECTION)
+                                       fSpecs.clear();
+                               else
+                                       prune();
+                       }
+               };
+               fRunDetector.addTypingRunListener(fRunListener);
+       }
+       
+       private void prune() {
+               for (Iterator it= fSpecs.values().iterator(); it.hasNext();) {
+                       UndoSpec spec= (UndoSpec) it.next();
+                       if (--spec.lives < 0)
+                               it.remove();
+               }
+       }
+       
+       /**
+        * Uninstalls the receiver. No undo specifications may be registered on an
+        * uninstalled manager.
+        */
+       public void uninstall() {
+               if (fViewer != null) {
+                       fRunDetector.removeTypingRunListener(fRunListener);
+                       fRunDetector.uninstall();
+                       fRunDetector= null;
+                       ensureListenerRemoved();
+                       fViewer= null;
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRun.java
new file mode 100644 (file)
index 0000000..350672a
--- /dev/null
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+
+
+/**
+ * Describes a run of similar typing changes.
+ * <p>
+ * XXX to be extended with further information, e.g. offset, length, and
+ * content of the run.
+ * </p>
+ * 
+ * @since 3.0
+ */
+public final class TypingRun {
+       /**
+        * A change of type <code>DELETE</code> deletes one single character (through delete or
+        * backspace or empty paste).
+        */ 
+       public static final ChangeType DELETE= new ChangeType(true, "DELETE"); //$NON-NLS-1$
+       /**
+        * A change of type <code>INSERT</code> inserts one single character
+        * (normal typing).
+        */ 
+       public static final ChangeType INSERT= new ChangeType(true, "INSERT"); //$NON-NLS-1$
+       /**
+        * A change of type <code>NO_CHANGE</code> does not change anything.
+        */
+       public static final ChangeType NO_CHANGE= new ChangeType(false, "NO_CHANGE"); //$NON-NLS-1$
+       /**
+        * A change of type <code>OVERTYPE</code> replaces one single character
+        * (overwrite mode, pasting a single character).
+        */
+       public static final ChangeType OVERTYPE= new ChangeType(true, "OVERTYPE"); //$NON-NLS-1$
+       /**
+        * A change of type <code>SELECTION</code> does not change text, but
+        * changes the focus, or selection. Such a change ends all typing runs.
+        */
+       public static final ChangeType SELECTION= new ChangeType(false, "SELECTION"); //$NON-NLS-1$
+       /**
+        * A change of type <code>UNKNOWN</code> modifies text in an
+        * unspecified way. An example is pasting more than one character, or 
+        * deleting an entire selection, or reverting a file. Such a change ends
+        * all typing runs and cannot form a typing run with any other change,
+        * including a change of type <code>UNKNOWN</code>.
+        */
+       public static final ChangeType UNKNOWN= new ChangeType(true, "UNKNOWN"); //$NON-NLS-1$
+
+
+       /**
+        * Enumeration of change types.
+        * 
+        * @since 3.0
+        */
+       public static final class ChangeType {
+               private final boolean fIsModification;
+               private final String fName;
+               
+               /** Private ctor for type safe enumeration. */
+               private ChangeType(boolean isRunPart, String name) {
+                       fIsModification= isRunPart;
+                       fName= name;
+               }
+               
+               /**
+                * Returns <code>true</code> if changes of this type modify text.
+                * 
+                * @return <code>true</code> if changes of this type modify text,
+                *         <code>false</code> otherwise
+                */
+               boolean isModification() {
+                       return fIsModification;
+               }
+               
+               /*
+                * @see java.lang.Object#toString()
+                */
+               public String toString() {
+                       return fName;
+               }
+       }
+       
+       /**
+        * Creates a new run.
+        * 
+        * @param type the type of the run
+        */
+       TypingRun(ChangeType type) {
+               this.type= type;
+       }
+       
+       /** The change type of this run. */
+       public final ChangeType type;
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/TypingRunDetector.java
new file mode 100644 (file)
index 0000000..61d59e1
--- /dev/null
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+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.jface.text.Assert;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.ITextListener;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.TextEvent;
+
+import net.sourceforge.phpdt.internal.ui.text.TypingRun.ChangeType;
+
+
+/**
+ * When connected to a text viewer, a <code>TypingRunDetector</code> observes
+ * <code>TypingRun</code> events. A typing run is a sequence of similar text
+ * modifications, such as inserting or deleting single characters.
+ * <p>
+ * Listeners are informed about the start and end of a <code>TypingRun</code>.
+ * </p>
+ * 
+ * @since 3.0
+ */
+public class TypingRunDetector {
+       /*
+        * Implementation note: This class is independent of JDT and may be pulled
+        * up to jface.text if needed.
+        */
+       
+       /** Debug flag. */
+       private static final boolean DEBUG= false;
+       
+       /**
+        * Instances of this class abstract a text modification into a simple
+        * description. Typing runs consists of a sequence of one or more modifying
+        * changes of the same type. Every change records the type of change
+        * described by a text modification, and an offset it can be followed by
+        * another change of the same run.
+        */
+       private static final class Change {
+               private ChangeType fType;
+               private int fNextOffset;
+               
+               /**
+                * Creates a new change of type <code>type</code>.
+                * 
+                * @param type the <code>ChangeType</code> of the new change
+                * @param nextOffset the offset of the next change in a typing run
+                */
+               public Change(ChangeType type, int nextOffset) {
+                       fType= type;
+                       fNextOffset= nextOffset;
+               }
+               
+               /**
+                * Returns <code>true</code> if the receiver can extend the typing
+                * range the last change of which is described by <code>change</code>.
+                * 
+                * @param change the last change in a typing run
+                * @return <code>true</code> if the receiver is a valid extension to
+                *         <code>change</code>,<code>false</code> otherwise
+                */
+               public boolean canFollow(Change change) {
+                       if (fType == TypingRun.NO_CHANGE)
+                               return true;
+                       else if (fType.equals(TypingRun.UNKNOWN))
+                               return false;
+                       if (fType.equals(change.fType)) {
+                               if (fType == TypingRun.DELETE)
+                                       return fNextOffset == change.fNextOffset - 1;
+                               else if (fType == TypingRun.INSERT)
+                                       return fNextOffset == change.fNextOffset + 1;
+                               else if (fType == TypingRun.OVERTYPE)
+                                       return fNextOffset == change.fNextOffset + 1;
+                               else if (fType == TypingRun.SELECTION)
+                                       return true;
+                       }
+                       return false;
+               }
+
+               /**
+                * Returns <code>true</code> if the receiver describes a text
+                * modification, <code>false</code> if it describes a focus /
+                * selection change.
+                * 
+                * @return <code>true</code> if the receiver is a text modification
+                */
+               public boolean isModification() {
+                       return fType.isModification();
+               }
+
+               /*
+                * @see java.lang.Object#toString()
+                */
+               public String toString() {
+                       return fType.toString() + "@" + fNextOffset; //$NON-NLS-1$
+               }
+               
+               /**
+                * Returns the change type of this change.
+                * 
+                * @return the change type of this change
+                */
+               public ChangeType getType() {
+                       return fType;
+               }
+       }
+       
+       /**
+        * Observes any events that modify the content of the document displayed in
+        * the editor. Since text events may start a new run, this listener is
+        * always registered if the detector is connected.
+        */
+       private class TextListener implements ITextListener {
+
+               /*
+                * @see org.eclipse.jface.text.ITextListener#textChanged(org.eclipse.jface.text.TextEvent)
+                */
+               public void textChanged(TextEvent event) {
+                       handleTextChanged(event);
+               }
+       }
+       
+       /**
+        * Observes non-modifying events that will end a run, such as clicking into
+        * the editor, moving the caret, and the editor losing focus. These events
+        * can never start a run, therefore this listener is only registered if
+        * there is an ongoing run.
+        */
+       private class SelectionListener implements MouseListener, KeyListener, FocusListener {
+
+               /*
+                * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+                */
+               public void focusGained(FocusEvent e) {
+                       handleSelectionChanged();
+               }
+
+               /*
+                * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+                */
+               public void focusLost(FocusEvent e) {
+               }
+               
+               /*
+                * @see MouseListener#mouseDoubleClick
+                */
+               public void mouseDoubleClick(MouseEvent e) {
+               }
+               
+               /*
+                * If the right mouse button is pressed, the current editing command is closed
+                * @see MouseListener#mouseDown
+                */
+               public void mouseDown(MouseEvent e) {
+                       if (e.button == 1)
+                               handleSelectionChanged();
+               }
+               
+               /*
+                * @see MouseListener#mouseUp
+                */
+               public void mouseUp(MouseEvent e) {
+               }
+
+               /*
+                * @see KeyListener#keyPressed
+                */
+               public void keyReleased(KeyEvent e) {
+               }
+               
+               /*
+                * On cursor keys, the current editing command is closed
+                * @see KeyListener#keyPressed
+                */
+               public void keyPressed(KeyEvent e) {
+                       switch (e.keyCode) {
+                               case SWT.ARROW_UP:
+                               case SWT.ARROW_DOWN:
+                               case SWT.ARROW_LEFT:
+                               case SWT.ARROW_RIGHT:
+                               case SWT.END:
+                               case SWT.HOME:
+                               case SWT.PAGE_DOWN:
+                               case SWT.PAGE_UP:
+                                       handleSelectionChanged();
+                                       break;
+                       }
+               }
+       }
+       
+       /** The listeners. */
+       private final Set fListeners= new HashSet();
+       /**
+        * The viewer we work upon. Set to <code>null</code> in
+        * <code>uninstall</code>.
+        */
+       private ITextViewer fViewer;
+       /** The text event listener. */
+       private final TextListener fTextListener= new TextListener();
+       /** 
+        * The selection listener. Set to <code>null</code> when no run is active.
+        */
+       private SelectionListener fSelectionListener;
+       
+       /* state variables */
+       
+       /** The most recently observed change. Never <code>null</code>. */
+       private Change fLastChange;
+       /** The current run, or <code>null</code> if there is none. */
+       private TypingRun fRun;
+       
+       /**
+        * Installs the receiver with a text viewer.
+        * 
+        * @param viewer the viewer to install on
+        */
+       public void install(ITextViewer viewer) {
+               Assert.isLegal(viewer != null);
+               fViewer= viewer;
+               connect();
+       }
+       
+       /**
+        * Initializes the state variables and registers any permanent listeners.
+        */
+       private void connect() {
+               if (fViewer != null) {
+                       fLastChange= new Change(TypingRun.UNKNOWN, -1);
+                       fRun= null;
+                       fSelectionListener= null;
+                       fViewer.addTextListener(fTextListener);
+               }
+       }
+
+       /**
+        * Uninstalls the receiver and removes all listeners. <code>install()</code>
+        * must be called for events to be generated.
+        */
+       public void uninstall() {
+               if (fViewer != null) {
+                       fListeners.clear();
+                       disconnect();
+                       fViewer= null;
+               }
+       }
+       
+       /**
+        * Disconnects any registered listeners.
+        */
+       private void disconnect() {
+               fViewer.removeTextListener(fTextListener);
+               ensureSelectionListenerRemoved();
+       }
+
+       /**
+        * Adds a listener for <code>TypingRun</code> events. Repeatedly adding
+        * the same listener instance has no effect. Listeners may be added even
+        * if the receiver is neither connected nor installed.
+        * 
+        * @param listener the listener add
+        */
+       public void addTypingRunListener(ITypingRunListener listener) {
+               Assert.isLegal(listener != null);
+               fListeners.add(listener);
+               if (fListeners.size() == 1)
+                       connect();
+       }
+       
+       /**
+        * Removes the listener from this manager. If <code>listener</code> is not
+        * registered with the receiver, nothing happens.
+        *  
+        * @param listener the listener to remove, or <code>null</code>
+        */
+       public void removeTypingRunListener(ITypingRunListener listener) {
+               fListeners.remove(listener);
+               if (fListeners.size() == 0)
+                       disconnect();
+       }
+       
+       /**
+        * Handles an incoming text event.
+        * 
+        * @param event the text event that describes the text modification
+        */
+       void handleTextChanged(TextEvent event) {
+               Change type= computeChange(event);
+               handleChange(type);
+       }
+
+       /**
+        * Computes the change abstraction given a text event.
+        * 
+        * @param event the text event to analyze
+        * @return a change object describing the event
+        */
+       private Change computeChange(TextEvent event) {
+               DocumentEvent e= event.getDocumentEvent();
+               if (e == null)
+                       return new Change(TypingRun.NO_CHANGE, -1);
+               
+               int start= e.getOffset();
+               int end= e.getOffset() + e.getLength();
+               String newText= e.getText();
+               if (newText == null)
+                       newText= new String();
+               
+               if (start == end) {
+                       // no replace / delete / overwrite
+                       if (newText.length() == 1)
+                               return new Change(TypingRun.INSERT, end + 1);
+               } else if (start == end - 1) {
+                       if (newText.length() == 1)
+                               return new Change(TypingRun.OVERTYPE, end);
+                       if (newText.length() == 0)
+                               return new Change(TypingRun.DELETE, start);
+               }
+               
+               return new Change(TypingRun.UNKNOWN, -1);
+       }
+       
+       /**
+        * Handles an incoming selection event.
+        */
+       void handleSelectionChanged() {
+               handleChange(new Change(TypingRun.SELECTION, -1));
+       }
+       
+       /**
+        * State machine. Changes state given the current state and the incoming
+        * change.
+        * 
+        * @param change the incoming change
+        */
+       private void handleChange(Change change) {
+               if (change.getType() == TypingRun.NO_CHANGE)
+                       return;
+               
+               if (DEBUG)
+                       System.err.println("Last change: " + fLastChange); //$NON-NLS-1$
+
+               if (!change.canFollow(fLastChange))
+                       endIfStarted(change);
+               fLastChange= change;
+               if (change.isModification())
+                       startOrContinue();
+               
+               if (DEBUG)
+                       System.err.println("New change: " + change); //$NON-NLS-1$
+       }
+
+       /**
+        * Starts a new run if there is none and informs all listeners. If there
+        * already is a run, nothing happens.
+        */
+       private void startOrContinue() {
+               if (!hasRun()) {
+                       if (DEBUG)
+                               System.err.println("+Start run"); //$NON-NLS-1$
+                       fRun= new TypingRun(fLastChange.getType());
+                       ensureSelectionListenerAdded();
+                       fireRunBegun(fRun);
+               }
+       }
+
+       /**
+        * Returns <code>true</code> if there is an active run, <code>false</code>
+        * otherwise.
+        * 
+        * @return <code>true</code> if there is an active run, <code>false</code>
+        *         otherwise
+        */
+       private boolean hasRun() {
+               return fRun != null;
+       }
+
+       /**
+        * Ends any active run and informs all listeners. If there is none, nothing
+        * happens.
+        * 
+        * @param change the change that triggered ending the active run
+        */
+       private void endIfStarted(Change change) {
+               if (hasRun()) {
+                       ensureSelectionListenerRemoved();
+                       if (DEBUG)
+                               System.err.println("-End run"); //$NON-NLS-1$
+                       fireRunEnded(fRun, change.getType());
+                       fRun= null;
+               }
+       }
+
+       /**
+        * Adds the selection listener to the text widget underlying the viewer, if
+        * not already done.
+        */
+       private void ensureSelectionListenerAdded() {
+               if (fSelectionListener == null) {
+                       fSelectionListener= new SelectionListener();
+                       StyledText textWidget= fViewer.getTextWidget();
+                       textWidget.addFocusListener(fSelectionListener);
+                       textWidget.addKeyListener(fSelectionListener);
+                       textWidget.addMouseListener(fSelectionListener);
+               }
+       }
+
+       /**
+        * If there is a selection listener, it is removed from the text widget
+        * underlying the viewer.
+        */
+       private void ensureSelectionListenerRemoved() {
+               if (fSelectionListener != null) {
+                       StyledText textWidget= fViewer.getTextWidget();
+                       textWidget.removeFocusListener(fSelectionListener);
+                       textWidget.removeKeyListener(fSelectionListener);
+                       textWidget.removeMouseListener(fSelectionListener);
+                       fSelectionListener= null;
+               }
+       }
+
+       /**
+        * Informs all listeners about a newly started <code>TypingRun</code>.
+        * 
+        * @param run the new run
+        */
+       private void fireRunBegun(TypingRun run) {
+               List listeners= new ArrayList(fListeners);
+               for (Iterator it= listeners.iterator(); it.hasNext();) {
+                       ITypingRunListener listener= (ITypingRunListener) it.next();
+                       listener.typingRunStarted(fRun);
+               }
+       }
+
+       /**
+        * Informs all listeners about an ended <code>TypingRun</code>.
+        * 
+        * @param run the previously active run
+        * @param reason the type of change that caused the run to be ended
+        */
+       private void fireRunEnded(TypingRun run, ChangeType reason) {
+               List listeners= new ArrayList(fListeners);
+               for (Iterator it= listeners.iterator(); it.hasNext();) {
+                       ITypingRunListener listener= (ITypingRunListener) it.next();
+                       listener.typingRunEnded(fRun, reason);
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/IJavaReconcilingListener.java
new file mode 100644 (file)
index 0000000..6fc5499
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import net.sourceforge.phpdt.core.dom.CompilationUnit;
+
+
+/**
+ * Interface of an object listening to Java reconciling.
+ * 
+ * @since 3.0
+ */
+public interface IJavaReconcilingListener {
+
+       /**
+        * Called before reconciling is started.
+        */
+       void aboutToBeReconciled();
+       
+       /**
+        * Called after reconciling has been finished.
+        * @param ast                           the compilation unit AST or <code>null</code> if
+ *                                                             the working copy was consistent or reconciliation has been cancelled
+        * @param forced                        <code>true</code> iff this reconciliation was forced
+        * @param progressMonitor       the progress monitor
+        */
+       void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor progressMonitor);
+}
index 319980b..56d3d75 100644 (file)
@@ -147,7 +147,7 @@ public class JavaStringAutoIndentStrategy extends DefaultAutoIndentStrategy {
 
        private void javaStringIndentAfterNewLine(IDocument document, DocumentCommand command) throws BadLocationException {
 
-               ITypedRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset);
+               ITypedRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset, false);
                int offset= partition.getOffset();
                int length= partition.getLength();
 
index cb927fb..5b5e1cf 100644 (file)
@@ -9,7 +9,6 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package net.sourceforge.phpdt.internal.ui.text.java.hover;
-
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -109,12 +108,12 @@ public class BestMatchHover extends AbstractJavaEditorTextHover implements IText
        }
 
        /*
-        * @see org.eclipse.jface.text.ITextHoverExtension#getInformationControlCreator()
+        * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
         * @since 3.0
         */
-       public IInformationControlCreator getInformationControlCreator() {
+       public IInformationControlCreator getHoverControlCreator() {
                if (fBestHover instanceof ITextHoverExtension)
-                       return ((ITextHoverExtension)fBestHover).getInformationControlCreator();
+                       return ((ITextHoverExtension)fBestHover).getHoverControlCreator();
 
                return null;
        }
@@ -129,4 +128,4 @@ public class BestMatchHover extends AbstractJavaEditorTextHover implements IText
 
                return null;
        }
-}
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/java/hover/SourceViewerInformationControl.java
new file mode 100644 (file)
index 0000000..2936e54
--- /dev/null
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.ui.text.java.hover;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
+import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlExtension;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Source viewer based implementation of <code>IInformationControl</code>. 
+ * Displays information in a source viewer. 
+ * 
+ * @since 3.0
+ */
+public class SourceViewerInformationControl implements IInformationControl, IInformationControlExtension, DisposeListener {
+       
+       /** Border thickness in pixels. */
+       private static final int BORDER= 1;
+       /** The control's shell */
+       private Shell fShell;
+       /** The control's text widget */
+       private StyledText fText;
+       /** The control's source viewer */
+       private SourceViewer fViewer;   
+       /**
+        * The optional status field.
+        * 
+        * @since 3.0
+        */
+       private Label fStatusField; 
+       /**
+        * The separator for the optional status field.
+        * 
+        * @since 3.0
+        */
+       private Label fSeparator; 
+       /**
+        * The font of the optional status text label.
+        * 
+        * @since 3.0
+        */
+       private Font fStatusTextFont;
+       
+       /**
+        * Creates a default information control with the given shell as parent. The given
+        * information presenter is used to process the information to be displayed. The given
+        * styles are applied to the created styled text widget.
+        * 
+        * @param parent the parent shell
+        * @param shellStyle the additional styles for the shell
+        * @param style the additional styles for the styled text widget
+        */
+       public SourceViewerInformationControl(Shell parent, int shellStyle, int style) {
+               this(parent, shellStyle, style, null);
+       }
+       
+       /**
+        * Creates a default information control with the given shell as parent. The given
+        * information presenter is used to process the information to be displayed. The given
+        * styles are applied to the created styled text widget.
+        * 
+        * @param parent the parent shell
+        * @param shellStyle the additional styles for the shell
+        * @param style the additional styles for the styled text widget
+        * @param statusFieldText the text to be used in the optional status field
+        *                         or <code>null</code> if the status field should be hidden
+        * @since 3.0
+        */
+       public SourceViewerInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) {
+               GridLayout layout;
+               GridData gd;
+
+               fShell= new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle);
+               Display display= fShell.getDisplay();           
+               fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+
+               Composite composite= fShell;
+               layout= new GridLayout(1, false);
+               int border= ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
+               layout.marginHeight= border;
+               layout.marginWidth= border;
+               composite.setLayout(layout);
+               gd= new GridData(GridData.FILL_HORIZONTAL);
+               composite.setLayoutData(gd);
+
+               if (statusFieldText != null) {
+                       composite= new Composite(composite, SWT.NONE);
+                       layout= new GridLayout(1, false);
+                       layout.marginHeight= 0;
+                       layout.marginWidth= 0;
+                       composite.setLayout(layout);
+                       gd= new GridData(GridData.FILL_BOTH);
+                       composite.setLayoutData(gd);
+                       composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+                       composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+               }               
+
+               // Source viewer
+               IPreferenceStore store= PHPeclipsePlugin.getDefault().getCombinedPreferenceStore();
+               fViewer= new JavaSourceViewer(composite, null, null, false, style, store);
+               fViewer.configure(new PHPSourceViewerConfiguration(PHPeclipsePlugin.getDefault().getJavaTextTools().getColorManager(), store, null, null));
+               fViewer.setEditable(false);
+               
+               fText= fViewer.getTextWidget();
+               gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
+               fText.setLayoutData(gd);
+               fText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+               fText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+                       
+               fText.addKeyListener(new KeyListener() {
+                               
+                       public void keyPressed(KeyEvent e)  {
+                               if (e.character == 0x1B) // ESC
+                                       fShell.dispose();
+                       }
+                               
+                       public void keyReleased(KeyEvent e) {}
+               });
+
+               // Status field
+               if (statusFieldText != null) {
+
+                       // Horizontal separator line
+                       fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT);
+                       fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+                       // Status field label
+                       fStatusField= new Label(composite, SWT.RIGHT);
+                       fStatusField.setText(statusFieldText);
+                       Font font= fStatusField.getFont();
+                       FontData[] fontDatas= font.getFontData();
+                       for (int i= 0; i < fontDatas.length; i++)
+                               fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
+                       fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas);
+                       fStatusField.setFont(fStatusTextFont);
+                       GridData gd2= new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING);
+                       fStatusField.setLayoutData(gd2);
+
+                       // Regarding the color see bug 41128
+                       fStatusField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
+
+                       fStatusField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+               }
+               
+               addDisposeListener(this);
+       }
+
+       /**
+        * Creates a default information control with the given shell as parent. The given
+        * information presenter is used to process the information to be displayed. The given
+        * styles are applied to the created styled text widget.
+        * 
+        * @param parent the parent shell
+        * @param style the additional styles for the styled text widget
+        */     
+       public SourceViewerInformationControl(Shell parent,int style) {
+               this(parent, SWT.NO_TRIM, style);
+       }
+       
+       /**
+        * Creates a default information control with the given shell as parent. The given
+        * information presenter is used to process the information to be displayed. The given
+        * styles are applied to the created styled text widget.
+        * 
+        * @param parent the parent shell
+        * @param style the additional styles for the styled text widget
+        * @param statusFieldText the text to be used in the optional status field
+        *                         or <code>null</code> if the status field should be hidden
+        * @since 3.0
+        */     
+       public SourceViewerInformationControl(Shell parent,int style, String statusFieldText) {
+               this(parent, SWT.NO_TRIM, style, statusFieldText);
+       }
+
+       /**
+        * Creates a default information control with the given shell as parent.
+        * No information presenter is used to process the information
+        * to be displayed. No additional styles are applied to the styled text widget.
+        * 
+        * @param parent the parent shell
+        */
+       public SourceViewerInformationControl(Shell parent) {
+               this(parent, SWT.NONE);
+       }
+
+       /**
+        * Creates a default information control with the given shell as parent.
+        * No information presenter is used to process the information
+        * to be displayed. No additional styles are applied to the styled text widget.
+        * 
+        * @param parent the parent shell
+        * @param statusFieldText the text to be used in the optional status field
+        *                         or <code>null</code> if the status field should be hidden
+        * @since 3.0
+        */
+       public SourceViewerInformationControl(Shell parent, String statusFieldText) {
+               this(parent, SWT.NONE, statusFieldText);
+       }
+       
+       /*
+        * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
+        */
+       public void setInput(Object input) {
+               if (input instanceof String)
+                       setInformation((String)input);
+               else
+                       setInformation(null);
+       }
+
+       /*
+        * @see IInformationControl#setInformation(String)
+        */
+       public void setInformation(String content) {
+               if (content == null) {
+                       fViewer.setInput(null);
+                       return;
+               }
+                               
+               IDocument doc= new Document(content);
+               PHPeclipsePlugin.getDefault().getJavaTextTools().setupJavaDocumentPartitioner(doc);
+               
+               fViewer.setInput(doc);
+       }
+       
+       /*
+        * @see IInformationControl#setVisible(boolean)
+        */
+       public void setVisible(boolean visible) {
+                       fShell.setVisible(visible);
+       }
+
+       /**
+        * {@inheritDoc}
+        * @since 3.0
+        */
+       public void widgetDisposed(DisposeEvent event) {
+               if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
+                       fStatusTextFont.dispose();
+               
+               fStatusTextFont= null;
+               fShell= null;
+               fText= null;
+       }
+               
+       /**
+        * {@inheritDoc}
+        */
+       public final void dispose() {
+               if (fShell != null && !fShell.isDisposed())
+                       fShell.dispose();
+               else
+                       widgetDisposed(null);
+       }
+       
+       /*
+        * @see IInformationControl#setSize(int, int)
+        */
+       public void setSize(int width, int height) {
+               
+               if (fStatusField != null) {
+                       GridData gd= (GridData)fViewer.getTextWidget().getLayoutData();
+                       Point statusSize= fStatusField.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+                       Point separatorSize= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
+                       gd.heightHint= height - statusSize.y - separatorSize.y;
+               }
+               fShell.setSize(width, height);
+               
+               if (fStatusField != null)
+                       fShell.pack(true);
+       }
+       
+       /*
+        * @see IInformationControl#setLocation(Point)
+        */
+       public void setLocation(Point location) {
+               Rectangle trim= fShell.computeTrim(0, 0, 0, 0);
+               Point textLocation= fText.getLocation();                                
+               location.x += trim.x - textLocation.x;          
+               location.y += trim.y - textLocation.y;          
+               fShell.setLocation(location);           
+       }
+       
+       /*
+        * @see IInformationControl#setSizeConstraints(int, int)
+        */
+       public void setSizeConstraints(int maxWidth, int maxHeight) {
+               maxWidth= maxHeight;
+       }
+       
+       /*
+        * @see IInformationControl#computeSizeHint()
+        */
+       public Point computeSizeHint() {
+               return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+       }
+       
+       /*
+        * @see IInformationControl#addDisposeListener(DisposeListener)
+        */
+       public void addDisposeListener(DisposeListener listener) {
+               fShell.addDisposeListener(listener);
+       }
+       
+       /*
+        * @see IInformationControl#removeDisposeListener(DisposeListener)
+        */
+       public void removeDisposeListener(DisposeListener listener) {
+               fShell.removeDisposeListener(listener);
+       }
+       
+       /*
+        * @see IInformationControl#setForegroundColor(Color)
+        */
+       public void setForegroundColor(Color foreground) {
+               fText.setForeground(foreground);
+       }
+       
+       /*
+        * @see IInformationControl#setBackgroundColor(Color)
+        */
+       public void setBackgroundColor(Color background) {
+               fText.setBackground(background);
+       }
+       
+       /*
+        * @see IInformationControl#isFocusControl()
+        */
+       public boolean isFocusControl() {
+               return fText.isFocusControl();
+       }
+       
+       /*
+        * @see IInformationControl#setFocus()
+        */
+       public void setFocus() {
+               fShell.forceFocus();
+               fText.setFocus();
+       }
+       
+       /*
+        * @see IInformationControl#addFocusListener(FocusListener)
+        */
+       public void addFocusListener(FocusListener listener) {
+               fText.addFocusListener(listener);
+       }
+       
+       /*
+        * @see IInformationControl#removeFocusListener(FocusListener)
+        */
+       public void removeFocusListener(FocusListener listener) {
+               fText.removeFocusListener(listener);
+       }
+       
+       /*
+        * @see IInformationControlExtension#hasContents()
+        */
+       public boolean hasContents() {
+               return fText.getCharCount() > 0;
+       }
+       
+       protected ISourceViewer getViewer()  {
+               return fViewer;
+       }
+}
index 11403b2..4fb0216 100644 (file)
@@ -722,7 +722,7 @@ public class LinkedPositionManager implements IDocumentListener, IPositionUpdate
                        
                        try {
                                if (position.getType().equals(currentPosition.getType()) && !position.equals(currentPosition))
-                                       command.addCommand(position.getOffset() + deltaOffset, command.length, command.text, true, this);
+                                       command.addCommand(position.getOffset() + deltaOffset, command.length, command.text, this);
                        } catch (BadLocationException e) {
                          PHPeclipsePlugin.log(e);
                        }
index 3be74d5..69bbfb9 100644 (file)
@@ -127,7 +127,6 @@ public class ProblemMarkerManager implements IResourceChangeListener, IAnnotatio
                        fireChanges(changes, true);
                }
        }
-       
        /* (non-Javadoc)
         * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
         */
@@ -141,14 +140,13 @@ public class ProblemMarkerManager implements IResourceChangeListener, IAnnotatio
        public void modelChanged(AnnotationModelEvent event) {
                if (event instanceof CompilationUnitAnnotationModelEvent) {
                        CompilationUnitAnnotationModelEvent cuEvent= (CompilationUnitAnnotationModelEvent) event;
-                       if (cuEvent.includesMarkerAnnotationChanges()) {
+                       if (cuEvent.includesProblemMarkerAnnotationChanges()) {
                                IResource[] changes= new IResource[] { cuEvent.getUnderlyingResource() };
                                fireChanges(changes, false);
                        }
                }
        }       
        
-       
        /**
         * Adds a listener for problem marker changes.
         */
index 946e308..5c025c8 100644 (file)
@@ -5,7 +5,6 @@ package net.sourceforge.phpdt.ui.text;
  * All Rights Reserved.
  */
 
-import net.sourceforge.phpdt.internal.ui.text.FastJavaPartitionScanner;
 import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
 import net.sourceforge.phpdt.internal.ui.text.JavaColorManager;
 import net.sourceforge.phpdt.internal.ui.text.phpdoc.PHPDocCodeScanner;
@@ -16,6 +15,7 @@ import net.sourceforge.phpeclipse.phpeditor.php.PHPPartitionScanner;
 import net.sourceforge.phpeclipse.phpeditor.php.SmartyCodeScanner;
 import net.sourceforge.phpeclipse.phpeditor.php.SmartyDocCodeScanner;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.text.IDocument;
@@ -26,6 +26,7 @@ import org.eclipse.jface.text.rules.IPartitionTokenScanner;
 import org.eclipse.jface.text.rules.RuleBasedScanner;
 import org.eclipse.jface.util.IPropertyChangeListener;
 import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.part.FileEditorInput;
 //
 //import org.phpeclipse.phpdt.internal.ui.text.FastJavaPartitionScanner;
 //import org.phpeclipse.phpdt.internal.ui.text.JavaColorManager;
@@ -364,25 +365,56 @@ public class JavaTextTools {
 
     return partitioner;
   }
-
        /**
-        * Sets up the Java document partitioner for the given document for the given partitioning.
+        * Sets up the Java document partitioner for the given document for the default partitioning.
         * 
         * @param document the document to be set up
+        * @since 3.0
+        */
+       public void setupJavaDocumentPartitioner(IDocument document) {
+               setupJavaDocumentPartitioner(document, IDocumentExtension3.DEFAULT_PARTITIONING,null);
+       }
+       /**
+        * Sets up the Java document partitioner for the given document for the given partitioning.
+        * @param document the document to be set up
         * @param partitioning the document partitioning
+        * @param element TODO
+        * 
         * @since 3.0
         */
-       public void setupJavaDocumentPartitioner(IDocument document, String partitioning) {
-               IDocumentPartitioner partitioner= createDocumentPartitioner();
-               if (document instanceof IDocumentExtension3) {
-                       IDocumentExtension3 extension3= (IDocumentExtension3) document;
-                       extension3.setDocumentPartitioner(partitioning, partitioner);
-               } else {
+       public void setupJavaDocumentPartitioner(IDocument document, String partitioning, Object element) {
+               IDocumentPartitioner partitioner = createDocumentPartitioner(".php");
+                        
+//             if (document instanceof IDocumentExtension3) {
+//                     IDocumentExtension3 extension3= (IDocumentExtension3) document;
+//                     extension3.setDocumentPartitioner(partitioning, partitioner);
+//             } else {
+                       document.setDocumentPartitioner(partitioner);
+//             }
+               partitioner.connect(document);
+       }
+       public void setupHTMLDocumentPartitioner(IDocument document, String partitioning, Object element) {
+               IDocumentPartitioner partitioner = createDocumentPartitioner(".html");
+                        
+//             if (document instanceof IDocumentExtension3) {
+//                     IDocumentExtension3 extension3= (IDocumentExtension3) document;
+//                     extension3.setDocumentPartitioner(partitioning, partitioner);
+//             } else {
+                       document.setDocumentPartitioner(partitioner);
+//             }
+               partitioner.connect(document);
+       }
+       public void setupSmartyDocumentPartitioner(IDocument document, String partitioning, Object element) {
+               IDocumentPartitioner partitioner = createDocumentPartitioner(".tpl");
+                        
+//             if (document instanceof IDocumentExtension3) {
+//                     IDocumentExtension3 extension3= (IDocumentExtension3) document;
+//                     extension3.setDocumentPartitioner(partitioning, partitioner);
+//             } else {
                        document.setDocumentPartitioner(partitioner);
-               }
+//             }
                partitioner.connect(document);
        }
-       
   /**
    * Returns the names of the document position categories used by the document
    * partitioners created by this object to manage their partition information.
index 30ed71c..7e4c33c 100644 (file)
@@ -5,11 +5,11 @@ import java.util.HashSet;
 import java.util.Set;
 
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
-import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
 import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.ui.texteditor.ITextEditor;
 
 /**
  * Modified from the XMLFormatter.  Some tags in HTML do not indent.
@@ -43,7 +43,7 @@ public class HTMLFormatter implements IHTMLConstants {
        private PHPSourceViewerConfiguration fConfig;
        private SourceViewer fViewer;
        //
-       private PHPEditor fEditor;
+       private ITextEditor fEditor;
        private String fFilename;
 
        ////////////////////////////////////////////////////////////////////////
index e3d00d4..2781272 100644 (file)
@@ -1,6 +1,5 @@
 package net.sourceforge.phpeclipse.phpeditor.html;
 
-import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
 import net.sourceforge.phpeclipse.phpeditor.PHPSourceViewerConfiguration;
 
 import org.eclipse.jface.text.BadLocationException;
@@ -8,6 +7,7 @@ import org.eclipse.jface.text.IDocument;
 import org.eclipse.jface.text.formatter.IFormattingStrategy;
 import org.eclipse.jface.text.source.ISourceViewer;
 import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.ui.texteditor.ITextEditor;
 
 /**
  * @author chrisl
@@ -24,7 +24,7 @@ public class HTMLFormattingStrategy implements IFormattingStrategy, IHTMLConstan
        private PHPSourceViewerConfiguration fConfig;
        private ISourceViewer fViewer;
        //
-       private PHPEditor fEditor;
+       private ITextEditor fEditor;
        private int fTabWidth;
 
        ////////////////////////////////////////////////////////////////////////